Sprytne Okazje — promocje, kody rabatowe i wyprzedaże

Pianino online

Graj na pianinie przez komputer lub tablet: klawiatura komputera jako klawisze, podgląd nut, nagrywanie. Nauka podstaw fortepianu online. Bezpłatnie.

Bezpieczne (SSL)
Przetwarzanie Lokalne
100% Darmowe
Instrukcja
  • 1
    Wprowadź dane
    Wpisz treść, wklej tekst lub załaduj plik z dysku.
  • 2
    Kliknij przycisk
    Narzędzie natychmiast przetworzy Twoje dane w przeglądarce.
  • 3
    Pobierz wynik
    Skopiuj gotowy tekst lub zapisz plik na urządzeniu.
function runTool() {
  return "Wynik gotowy w 0.1s";
}
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Pro Online Piano Synth</title>
  
  <style>
    :root { --radius: 16px; --bg: #0b1220; --card-bg: rgba(255,255,255,0.04); --border: rgba(255,255,255,0.1); --text: #eef2ff; --muted: rgba(238,242,255,0.6); --accent: #6366f1; }
    * { box-sizing: border-box; }
    body { margin: 0; padding: 20px; font-family: system-ui, -apple-system, sans-serif; background: var(--bg); color: var(--text); min-height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center; }
    .wrap { width: 100%; max-width: 900px; background: var(--card-bg); border: 1px solid var(--border); border-radius: var(--radius); padding: 24px; box-shadow: 0 8px 32px rgba(0,0,0,0.2); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); }
    h1 { margin: 0 0 10px 0; font-size: 24px; font-weight: 700; display: flex; align-items: center; gap: 10px; }
    .status { display: inline-block; width: 10px; height: 10px; border-radius: 50%; background: #ef4444; box-shadow: 0 0 8px #ef4444; }
    .status.active { background: #22c55e; box-shadow: 0 0 8px #22c55e; }
    p { margin: 0 0 20px 0; color: var(--muted); line-height: 1.5; font-size: 14px; }
    .kbd { background: rgba(0,0,0,0.5); border: 1px solid var(--border); padding: 3px 6px; border-radius: 6px; font-family: monospace; font-size: 12px; color: #a5b4fc; }
    .piano-wrap { background: rgba(0,0,0,0.2); border: 1px solid var(--border); border-radius: 12px; padding: 16px; margin-bottom: 16px; overflow-x: auto; }
    canvas { width: 100%; height: 100px; background: #000; border-radius: 8px; margin-bottom: 16px; border: 1px solid var(--border); display: block; }
    svg { min-width: 600px; width: 100%; height: auto; display: block; }
    .key { cursor: pointer; user-select: none; -webkit-user-select: none; touch-action: none; }
    .white { fill: #f8fafc; stroke: #cbd5e1; stroke-width: 1; transition: fill 0.1s; }
    .black { fill: #111827; stroke: #000; stroke-width: 1; transition: fill 0.1s; }
    .active.white { fill: #c7d2fe; }
    .active.black { fill: #6366f1; }
    .label { font-size: 11px; fill: rgba(0,0,0,0.5); pointer-events: none; }
    .label.black { fill: rgba(255,255,255,0.7); }
    .btn { appearance: none; background: var(--accent); color: #fff; border: none; padding: 10px 20px; border-radius: 8px; font-weight: 600; cursor: pointer; transition: 0.2s; font-size: 14px; }
    .btn:hover { background: #4f46e5; }
    .btn:active { transform: scale(0.98); }
    .toolbar { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; flex-wrap: wrap; gap: 10px; }
  </style>
</head>
<body>
  <div class="wrap">
    <h1><span id="status-dot" class="status"></span> Pro Online Piano Synth</h1>
    <p>Use your mouse/touch or keyboard (<span class="kbd">A</span> <span class="kbd">W</span> <span class="kbd">S</span> <span class="kbd">E</span> <span class="kbd">D</span> <span class="kbd">F</span> <span class="kbd">T</span> <span class="kbd">G</span> <span class="kbd">Y</span> <span class="kbd">H</span> <span class="kbd">U</span> <span class="kbd">J</span>) to play.</p>
    
    <div class="toolbar">
      <button class="btn" id="enable-audio" type="button">Initialize Audio Engine</button>
      <span style="color:var(--muted); font-size:12px;" id="poly-count">Voices: 0 / 8</span>
    </div>

    <canvas id="oscilloscope" width="840" height="100" aria-label="Audio Visualizer"></canvas>

    <div class="piano-wrap">
      <svg id="keyboard" viewBox="0 0 840 180" aria-label="Piano keyboard" role="img"></svg>
    </div>
  </div>

  <script>
  (function () {
    'use strict';
    const CONFIG = {"octaves":2,"base_octave":3,"waveform":"triangle","attack":0.0200000000000000004163336342344337026588618755340576171875,"decay":0.1499999999999999944488848768742172978818416595458984375,"sustain":0.5500000000000000444089209850062616169452667236328125,"release":0.34999999999999997779553950749686919152736663818359375,"volume":0.75,"polyphony":8,"show_labels":1,"filter_cutoff":20000,"filter_reso":0,"detune":0,"visualizer":1};
    const NOTE_NAMES = ["C","C#","D","D#","E","F","F#","G","G#","A","A#","B"];
    const WHITE_ORDER = ["C","D","E","F","G","A","B"];
    const keyMap = { "a":"C","w":"C#","s":"D","e":"D#","d":"E","f":"F","t":"F#","g":"G","y":"G#","h":"A","u":"A#","j":"B" };

    let ctx, master, analyser, filterNode;
    const voices = new Map(); 
    let voiceOrder = [];

    const svg = document.getElementById("keyboard");
    const btnEnable = document.getElementById("enable-audio");
    const statusDot = document.getElementById("status-dot");
    const polyCount = document.getElementById("poly-count");
    const canvas = document.getElementById("oscilloscope");
    const canvasCtx = canvas ? canvas.getContext("2d") : null;

    function clamp(v, a, b) { return Math.max(a, Math.min(b, Number(v))); }
    function noteToMidi(note, octave) { return 12 * (octave + 1) + NOTE_NAMES.indexOf(note); }
    function midiToFreq(midi) { return 440 * Math.pow(2, (midi - 69) / 12); }
    function makeId(note, octave) { return note + String(octave); }

    async function initAudio() {
      if (ctx) return;
      ctx = new (window.AudioContext || window.webkitAudioContext)();
      
      master = ctx.createGain();
      master.gain.value = clamp(CONFIG.volume, 0.05, 1);
      
      filterNode = ctx.createBiquadFilter();
      filterNode.type = "lowpass";
      filterNode.frequency.value = clamp(CONFIG.filter_cutoff, 20, 20000);
      filterNode.Q.value = clamp(CONFIG.filter_reso, 0, 30);
      
      if (CONFIG.visualizer && canvasCtx) {
        analyser = ctx.createAnalyser();
        analyser.fftSize = 2048;
        filterNode.connect(master);
        master.connect(analyser);
        analyser.connect(ctx.destination);
        drawOscilloscope();
      } else {
        filterNode.connect(master);
        master.connect(ctx.destination);
      }
      
      if (ctx.state === "suspended") await ctx.resume();
      
      statusDot.classList.add("active");
      btnEnable.style.display = "none";
    }

    function drawOscilloscope() {
      if (!analyser || !canvasCtx) return;
      requestAnimationFrame(drawOscilloscope);
      const bufferLength = analyser.frequencyBinCount;
      const dataArray = new Uint8Array(bufferLength);
      analyser.getByteTimeDomainData(dataArray);

      canvasCtx.fillStyle = "#000";
      canvasCtx.fillRect(0, 0, canvas.width, canvas.height);
      canvasCtx.lineWidth = 2;
      canvasCtx.strokeStyle = "#6366f1";
      canvasCtx.beginPath();

      const sliceWidth = canvas.width * 1.0 / bufferLength;
      let x = 0;
      for (let i = 0; i < bufferLength; i++) {
        const v = dataArray[i] / 128.0;
        const y = v * canvas.height / 2;
        if (i === 0) canvasCtx.moveTo(x, y);
        else canvasCtx.lineTo(x, y);
        x += sliceWidth;
      }
      canvasCtx.lineTo(canvas.width, canvas.height / 2);
      canvasCtx.stroke();
    }

    function scheduleEnvelope(gainNode, when, isOn) {
      const g = gainNode.gain;
      g.cancelScheduledValues(when);
      if (isOn) {
        g.setValueAtTime(0.0001, when);
        g.linearRampToValueAtTime(1.0, when + Math.max(0.001, CONFIG.attack));
        g.linearRampToValueAtTime(Math.max(0.0001, CONFIG.sustain), when + Math.max(0.001, CONFIG.attack) + Math.max(0.001, CONFIG.decay));
      } else {
        const cur = Math.max(0.0001, g.value);
        g.setValueAtTime(cur, when);
        g.linearRampToValueAtTime(0.0001, when + Math.max(0.01, CONFIG.release));
      }
    }

    function updatePolyCount() {
      if(polyCount) polyCount.textContent = `Voices: ${voices.size} / ${CONFIG.polyphony}`;
    }

    function startVoice(note, octave) {
      initAudio();
      if (!ctx || !filterNode) return;
      const id = makeId(note, octave);
      if (voices.has(id)) return;

      while (voices.size >= clamp(CONFIG.polyphony, 1, 16) && voiceOrder.length) {
        stopVoice(voiceOrder.shift(), true);
      }

      const osc = ctx.createOscillator();
      const gain = ctx.createGain();
      
      osc.type = CONFIG.waveform || "triangle";
      osc.frequency.value = midiToFreq(noteToMidi(note, octave));
      osc.detune.value = CONFIG.detune || 0;
      gain.gain.value = 0.0001;

      osc.connect(gain);
      gain.connect(filterNode);

      const t = ctx.currentTime;
      scheduleEnvelope(gain, t, true);
      osc.start(t);

      voices.set(id, { osc, gain });
      voiceOrder.push(id);
      
      const el = svg.querySelector(`[data-id="${id.replace(/"/g, '\"')}"]`);
      if (el) el.classList.add("active");
      updatePolyCount();
    }

    function stopVoice(id, immediate) {
      const v = voices.get(id);
      if (!v || !ctx) return;
      const t = ctx.currentTime;
      scheduleEnvelope(v.gain, t, false);
      const stopAt = immediate ? (t + 0.02) : (t + Math.max(0.05, CONFIG.release) + 0.02);
      try { v.osc.stop(stopAt); } catch (e) {}
      voices.delete(id);
      voiceOrder = voiceOrder.filter(x => x !== id);
      const el = svg.querySelector(`[data-id="${id.replace(/"/g, '\"')}"]`);
      if (el) el.classList.remove("active");
      updatePolyCount();
    }

    function buildKeyboard() {
      const octaves = clamp(CONFIG.octaves, 1, 4);
      const baseOct = clamp(CONFIG.base_octave, 1, 7);
      while (svg.firstChild) svg.removeChild(svg.firstChild);

      const wW = 60, wH = 170, bW = 38, bH = 110;
      svg.setAttribute("viewBox", `0 0 ${octaves * 7 * wW} 180`);

      let x = 0;
      for (let o = 0; o < octaves; o++) {
        const oct = baseOct + o;
        for (const n of WHITE_ORDER) {
          const id = makeId(n, oct);
          const g = document.createElementNS("http://www.w3.org/2000/svg", "g");
          g.setAttribute("class", "key");
          g.dataset.id = id; g.dataset.note = n; g.dataset.octave = oct;

          const r = document.createElementNS("http://www.w3.org/2000/svg", "rect");
          r.setAttribute("x", x); r.setAttribute("y", 0);
          r.setAttribute("rx", 6); r.setAttribute("ry", 6);
          r.setAttribute("width", wW); r.setAttribute("height", wH);
          r.setAttribute("class", "white");
          g.appendChild(r);

          if (CONFIG.show_labels) {
            const t = document.createElementNS("http://www.w3.org/2000/svg", "text");
            t.setAttribute("x", x + wW/2); t.setAttribute("y", wH - 18);
            t.setAttribute("text-anchor", "middle"); t.setAttribute("class", "label");
            t.textContent = n + oct;
            g.appendChild(t);
          }
          svg.appendChild(g);
          x += wW;
        }
      }

      for (let o = 0; o < octaves; o++) {
        const oct = baseOct + o;
        const bPos = [{n:"C#",p:0},{n:"D#",p:1},{n:"F#",p:3},{n:"G#",p:4},{n:"A#",p:5}];
        for (const bp of bPos) {
          const id = makeId(bp.n, oct);
          const bx = (o * 7 + bp.p + 1) * wW - bW/2;
          const g = document.createElementNS("http://www.w3.org/2000/svg", "g");
          g.setAttribute("class", "key");
          g.dataset.id = id; g.dataset.note = bp.n; g.dataset.octave = oct;

          const r = document.createElementNS("http://www.w3.org/2000/svg", "rect");
          r.setAttribute("x", bx); r.setAttribute("y", 0);
          r.setAttribute("rx", 4); r.setAttribute("ry", 4);
          r.setAttribute("width", bW); r.setAttribute("height", bH);
          r.setAttribute("class", "black");
          g.appendChild(r);

          if (CONFIG.show_labels) {
            const t = document.createElementNS("http://www.w3.org/2000/svg", "text");
            t.setAttribute("x", bx + bW/2); t.setAttribute("y", bH - 18);
            t.setAttribute("text-anchor", "middle"); t.setAttribute("class", "label black");
            t.textContent = bp.n + oct;
            g.appendChild(t);
          }
          svg.appendChild(g);
        }
      }
    }

    const pressed = new Map();
    const getKeyInfo = (t) => {
      const g = t?.closest?.(".key");
      return g ? { id: g.dataset.id, note: g.dataset.note, oct: Number(g.dataset.octave) } : null;
    };

    svg.addEventListener("pointerdown", (e) => {
      const k = getKeyInfo(e.target);
      if (!k) return;
      svg.setPointerCapture(e.pointerId);
      pressed.set(e.pointerId, k.id);
      startVoice(k.note, k.oct);
      e.preventDefault();
    });

    svg.addEventListener("pointermove", (e) => {
      if (!pressed.has(e.pointerId)) return;
      const prev = pressed.get(e.pointerId);
      const k = getKeyInfo(e.target);
      if (k && k.id !== prev) {
        stopVoice(prev, false);
        pressed.set(e.pointerId, k.id);
        startVoice(k.note, k.oct);
      }
    });

    const endPointer = (e) => {
      const id = pressed.get(e.pointerId);
      if (id) stopVoice(id, false);
      pressed.delete(e.pointerId);
    };
    svg.addEventListener("pointerup", endPointer);
    svg.addEventListener("pointercancel", endPointer);

    const downKeys = new Set();
    window.addEventListener("keydown", (e) => {
      const k = (e.key || "").toLowerCase();
      if (!keyMap[k] || downKeys.has(k)) return;
      downKeys.add(k);
      startVoice(keyMap[k], clamp(CONFIG.base_octave, 1, 7));
    });
    window.addEventListener("keyup", (e) => {
      const k = (e.key || "").toLowerCase();
      if (!keyMap[k]) return;
      downKeys.delete(k);
      stopVoice(makeId(keyMap[k], clamp(CONFIG.base_octave, 1, 7)), false);
    });

    if (btnEnable) btnEnable.addEventListener("click", initAudio);
    
    buildKeyboard();
  })();
  </script>
</body>
</html>
filename: online-piano.html

Oceń to narzędzie:

Powiązane narzędzia

Inne narzędzia, które mogą Ci się przydać

Pianino online – graj na fortepianie w przeglądarce

Pianino online to wirtualny instrument dostępny bez instalacji – bezpośrednio w przeglądarce. Obsługiwane przez klawiaturę komputera, mysz lub ekran dotykowy. Idealne do nauki podstaw, eksperymentowania z melodiami, ćwiczenia palców i zabawy z muzyką.

pianino online wirtualny fortepian klawiatura pianino graj na pianinie online

Jak używać pianina online

Klawiatura komputera: klawisze A-L, W-O odpowiadają klawiszom fortepianu (biały i czarny). Mysz/dotyk: kliknij lub dotknij wirtualny klawisz. MIDI: podłącz klawiaturę MIDI przez Web MIDI API (Chrome). Oktawy: przełącz góra/dół by zmienić rejestr. Sustain: Shift trzyma dźwięk (jak pedał). Volume: slider głośności.

Klawiszownik fortepianu

Fortepian ma 88 klawiszy: 52 białe, 36 czarnych. Środkowe C (C4): centralne C, odniesienie dla strojenia. Oktawy: C1-C8, każda wyżej o 2× wyższą częstotliwość. A4 = 440 Hz (standard strojenia). Klawisze czarne (półtony): C#/Db, D#/Eb, F#/Gb, G#/Ab, A#/Bb. Gama C-dur: wszystkie białe klawisze C D E F G A B C.

Podstawowe akordy fortepianowe

C-dur: C + E + G (1, 3, 5 stopień gamy C). G-dur: G + B + D. Am (a-moll): A + C + E. F-dur: F + A + C. Progresja 1-4-5: C-F-G (wiele piosenek pop). Progresja 1-5-6-4: C-G-Am-F = "Pachelbel Canon progression" (Let It Be, No Woman No Cry, itp.). Narzędzie podświetla klawisze akordów.

Nauka gry na pianinie

Postura: prostowane plecy, ręce na wysokości klawiatury. Palce: lekko zaokrąglone (jakbyś trzymał piłkę). Lewa ręka: akompaniament (akordy). Prawa ręka: melodia. Ćwiczenie: ćwicz każdą rękę osobno, potem razem. Metronomem: zawsze ćwicz z metronomem. Aplikacje: Simply Piano, Flowkey, Playground Sessions dla zorganizowanej nauki.

Najczęstsze pytania

Czy pianino online zastąpi prawdziwy instrument?

Nie – pianino online jest dobre do: eksperymentowania, podstaw teorii, zabawy, ćwiczenia melodii. Brakuje: "touch response" (dynamika nacisku), pedał (sustain), fizycznej nauki układu klawiatury, satysfakcji z prawdziwego instrumentu. Do poważnej nauki: kup klawiaturę MIDI (88 klawiszy, weighted keys) od 300-600 zł.

Jak szybko nauczyć się grać prostą melodię?

Wybierz prostą melodię: "Oda do radości", "Happy Birthday", gamę C-dur. Zidentyfikuj nuty: skorzystaj z tutorialu nut. Ćwicz wolno: jedna nuta na raz. Zapamiętaj sekwencję bez patrzenia na nuty. Stopniowo przyspieszaj. Użyj oznaczeń palców. Prosta melodia = 30-60 minut ćwiczeń.

Jaki jest najlepszy sposób na naukę pianina online?

Structured apps: Simply Piano (gamifikacja, świetna dla dzieci), Flowkey (tysiące piosenek), Playground Sessions (z Quincy Jonesem). YouTube: Piano Tutorial Show, Rousseau (visualizacje). Teoria: musictheory.net. Nauczyciel online: Preply, AmazingTalker. Samouczek: "Alfred's Adult All-in-One Piano Course" dla dorosłych.

Co to jest MIDI i jak działa z pianinem online?

MIDI (Musical Instrument Digital Interface): standard komunikacji instrumentów. Klawiatura MIDI wysyła sygnały (nota on/off, velocity) do komputera. Web MIDI API (Chrome): przeglądarka może odbierać MIDI. Narzędzie pianino obsługuje Web MIDI jeśli masz klawiaturę MIDI podłączoną przez USB. Programy: GarageBand (Mac), LMMS (darmowy) do nagrywania MIDI.

Jak rozpoznać nuty na pięciolinii?

Treble clef (wiolinowy, lewa ręka prawa ręka wyższe): linie EGBDF (Every Good Boy Does Fine), przestrzenie FACE. Bass clef (basowy): linie GBDFA (Good Boys Do Fine Always), przestrzenie ACEG (All Cows Eat Grass). Środkowe C: między obu pięcioliniami (mała linia pomocnicza). Nuta: głowa + ogonek + belki (dla krótkich wartości).

Powiązane narzedzia: pianino MIDI recorder, metronom online i generator akordow gitarowych.

Zainstaluj Webp.pl Miej narzędzia we własnej kieszeni!