So codieren Sie eine spielbare Synth -Tastatur
Mit nur ein wenig Kenntnis der Musiktheorie können wir gewöhnliche HTML, CSS und JavaScript (keine Bibliotheken oder Audioproben erforderlich) verwenden, um ein einfaches digitales Instrument zu erstellen. Lassen Sie es uns in die Praxis umsetzen und einen Weg erforschen, um einen digitalen Synthesizer zu erstellen, der im Internet gespielt und gehostet werden kann.
Hier ist, was wir machen wollen:
Wir werden die Audiocontext -API verwenden, um unsere Stimme digital zu erstellen, ohne sich auf Samples zu verlassen. Aber zuerst zuerst zuerst das Erscheinungsbild der Tastatur zuerst zu tun.
HTML -Struktur
Wir werden eine Standard -westliche Tastatur unterstützen, in der jeder Buchstaben zwischen A bis eine spielbare natürliche Note (weiße Taste) entspricht, während die obigen Linien zum Aufstieg und Downing verwendet werden können (schwarze Taste). Dies bedeutet, dass unsere Tastatur etwas mehr als eine Oktave abdeckt, beginnend bei C₃ und endet bei E₄. (Für alle, die mit der Punktzahl nicht vertraut sind, geben die Indexnummern die Oktave an.)
Eine nützliche Sache, die wir tun können, ist, den Note -Wert in einer benutzerdefinierten Note -Eigenschaft zu speichern, damit er in unserem JavaScript problemlos zugegriffen werden kann. Ich werde Buchstaben auf meiner Computertastatur drucken, um unseren Benutzern zu verstehen, welche Tasten zu drücken sind.
<code></code>
- A
- W
- S
- E
- D
- F
- T
- G
- Y
- H
- U
- J
- K
- O
- L
- P
- ;
CSS -Stil
Wir beginnen mit einer Kesselplatte für unser CSS:
<code>html { box-sizing: border-box; } *, *:before, *:after { box-sizing: inherit; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; } body { margin: 0; }</code>
Lassen Sie uns die CSS -Variable für einige der Farben angeben, die wir verwenden. Fühlen Sie sich frei, zu jeder Farbe zu wechseln, die Sie mögen!
<code>:root { --keyboard: hsl(300, 100%, 16%); --keyboard-shadow: hsla(19, 50%, 66%, 0.2); --keyboard-border: hsl(20, 91%, 5%); --black-10: hsla(0, 0%, 0%, 0.1); --black-20: hsla(0, 0%, 0%, 0.2); --black-30: hsla(0, 0%, 0%, 0.3); --black-50: hsla(0, 0%, 0%, 0.5); --black-60: hsla(0, 0%, 0%, 0.6); --white-20: hsla(0, 0%, 100%, 0.2); --white-50: hsla(0, 0%, 100%, 0.5); --white-80: hsla(0, 0%, 100%, 0.8); }</code>
Insbesondere verändert das Ändern der Variablen-Keeboard und-Keeyboard-Gr-Größen das Endergebnis stark.
Für Stilschlüsse und Tastaturen - besonders beim Drücken - war ich von diesem Codepen aus Zastrow inspiriert. Zunächst geben wir die CSS für alle Schlüsselfreigabe an:
<code>.white, .black { position: relative; float: left; display: flex; justify-content: center; align-items: flex-end; padding: 0.5rem 0; user-select: none; cursor: pointer; }</code>
Die Verwendung spezifischer abgerundeter Ecken an den ersten und letzten Schlüssel hilft, das Design natürlicher aussehen zu lassen. Ohne abgerundete Ecken sehen die oberen linken und oberen rechten Ecken des Schlüssels etwas unnatürlich aus. Dies ist ein endgültiges Design, abzüglich aller zusätzlichen abgerundeten Ecken in den ersten und letzten Schlüssel.
Fügen wir einige CSS hinzu, um dies zu verbessern.
<code>#keyboard li:first-child { border-radius: 5px 0 5px 5px; } #keyboard li:last-child { border-radius: 0 5px 5px 5px; }</code>
Der Unterschied ist subtil, aber effektiv:
Als nächstes wenden wir Stile an, die weiße und schwarze Schlüssel unterscheiden. Beachten Sie, dass der Z-Index für den weißen Schlüssel 1 und der Z-Index für den schwarzen Schlüssel 2 beträgt:
<code>.white { height: 12.5rem; width: 3.5rem; z-index: 1; border-left: 1px solid hsl(0, 0%, 73%); border-bottom: 1px solid hsl(0, 0%, 73%); border-radius: 0 0 5px 5px; box-shadow: -1px 0 0 var(--white-80) inset, 0 0 5px hsl(0, 0%, 80%) inset, 0 0 3px var(--black-20); background: linear-gradient(to bottom, hsl(0, 0%, 93%) 0%, white 100%); color: var(--black-30); } .black { height: 8rem; width: 2rem; margin: 0 0 0 -1rem; z-index: 2; border: 1px solid black; border-radius: 0 0 3px 3px; box-shadow: -1px -1px 2px var(--white-20) inset, 0 -5px 2px 3px var(--black-60) inset, 0 2px 4px var(--black-50); background: linear-gradient(45deg, hsl(0, 0%, 13%) 0%, hsl(0, 0%, 33%) 100%); color: var(--white-50); }</code>
Wenn wir die Taste drücken, verwenden wir JavaScript, um dem entsprechenden Li -Element eine "gedrückte" Klasse hinzuzufügen. Jetzt können wir dies testen, indem wir die Klasse direkt zu unserem HTML -Element hinzufügen.
<code>.white.pressed { border-top: 1px solid hsl(0, 0%, 47%); border-left: 1px solid hsl(0, 0%, 60%); border-bottom: 1px solid hsl(0, 0%, 60%); box-shadow: 2px 0 3px var(--black-10) inset, -5px 5px 20px var(--black-20) inset, 0 0 3px var(--black-20); background: linear-gradient(to bottom, white 0%, hsl(0, 0%, 91%) 100%); outline: none; } .black.pressed { box-shadow: -1px -1px 2px var(--white-20) inset, 0 -2px 2px 3px var(--black-60) inset, 0 1px 2px var(--black-50); background: linear-gradient( to right, hsl(0, 0%, 27%) 0%, hsl(0, 0%, 13%) 100% ); outline: none; }</code>
Einige weiße Schlüssel müssen links bewegt werden, damit sie unter den schwarzen Schlüssel liegen. Wir weisen diese Schlüssel der "Offset" -Klasse in HTML zu, damit wir CSS einfach halten können:
<code>.offset { margin: 0 0 0 -1rem; }</code>
Wenn Sie diesem CSS gefolgt sind, sollten Sie so etwas haben:
Schließlich werden wir die Tastatur selbst stylen:
<code>#keyboard { height: 15.25rem; width: 41rem; margin: 0.5rem auto; padding: 3rem 0 0 3rem; position: relative; border: 1px solid var(--keyboard-border); border-radius: 1rem; background-color: var(--keyboard); box-shadow: 0 0 50px var(--black-50) inset, 0 1px var(--keyboard-shadow) inset, 0 5px 15px var(--black-50); }</code>
Wir haben jetzt eine gut aussehende CSS -Tastatur, aber es ist nicht interaktiv und macht keinen Ton. Dazu brauchen wir JavaScript.
Musik JavaScript
Um die Soundeffekte des Synthesizers zu erstellen, möchten wir uns nicht auf Audio -Samples verlassen - das ist Betrug! Stattdessen können wir die Audiocontext -API des Netzwerks verwenden, die Tools enthält, mit denen wir digitale Wellenformen in Ton umwandeln können.
Um einen neuen Audiokontext zu erstellen, können wir verwenden:
<code>const audioContext = new (window.AudioContext || window.webkitAudioContext)();</code>
Bevor wir unseren Audiocontext verwenden, ist es hilfreich, alle Notizenelemente in HTML auszuwählen. Wir können leicht Elemente mit dieser Helferfunktion abfragen:
<code>const getElementByNote = (note) => note && document.querySelector(`[note="${note}"]`);</code>
Wir können dann das Element in einem Objekt speichern, bei dem die Taste des Objekts eine Taste ist, die der Benutzer auf die Tastatur drückt, um diese Notiz abzuspielen.
<code>const keys = { A: { element: getElementByNote("C"), note: "C", octaveOffset: 0 }, W: { element: getElementByNote("C#"), note: "C#", octaveOffset: 0 }, S: { element: getElementByNote("D"), note: "D", octaveOffset: 0 }, E: { element: getElementByNote("D#"), note: "D#", octaveOffset: 0 }, D: { element: getElementByNote("E"), note: "E", octaveOffset: 0 }, F: { element: getElementByNote("F"), note: "F", octaveOffset: 0 }, T: { element: getElementByNote("F#"), note: "F#", octaveOffset: 0 }, G: { element: getElementByNote("G"), note: "G", octaveOffset: 0 }, Y: { element: getElementByNote("G#"), note: "G#", octaveOffset: 0 }, H: { element: getElementByNote("A"), note: "A", octaveOffset: 1 }, U: { element: getElementByNote("A#"), note: "A#", octaveOffset: 1 }, J: { element: getElementByNote("B"), note: "B", octaveOffset: 1 }, K: { element: getElementByNote("C2"), note: "C", octaveOffset: 1 }, O: { element: getElementByNote("C#2"), note: "C#", octaveOffset: 1 }, L: { element: getElementByNote("D2"), note: "D", octaveOffset: 1 }, P: { element: getElementByNote("D#2"), note: "D#", octaveOffset: 1 }, semicolon: { element: getElementByNote("E2"), note: "E", octaveOffset: 1 } };</code>
Ich fand es nützlich, den Namen der Notizen hier und OctaveOffset anzugeben, der bei der Berechnung der Tonhöhe benötigt wird.
Wir müssen in Hz eine Tonhöhe bereitstellen. Die Gleichung zur Bestimmung der Tonhöhe beträgt x * 2^(y / 12), wobei x der Hz -Wert der ausgewählten Note ist - normalerweise A₄ mit einer Tonhöhe von 440 Hz - und y ist die Anzahl der Noten über oder unter dieser Tonhöhe.
Dies gibt uns so etwas im Code:
<code>const getHz = (note = "A", octave = 4) => { const A4 = 440; let N = 0; switch (note) { default: case "A": N = 0; break; case "A#": case "Bb": N = 1; break; case "B": N = 2; break; case "C": N = 3; break; case "C#": case "Db": N = 4; break; case "D": N = 5; break; case "D#": case "Eb": N = 6; break; case "E": N = 7; break; case "F": N = 8; break; case "F#": case "Gb": N = 9; break; case "G": N = 10; break; case "G#": case "Ab": N = 11; break; } N = 12 * (octave - 4); return A4 * Math.pow(2, N / 12); };</code>
Obwohl wir im Rest des Codes nur Upshots verwenden, habe ich beschlossen, hier auch Downs aufzunehmen, damit diese Funktion in verschiedenen Kontexten leicht wiederverwendet werden kann.
Für alle, die sich beispielsweise über die Punktzahl nicht sicher sind, beschreiben beispielsweise eine# und BB genau die gleiche Tonhöhe. Wenn wir in einer bestimmten Melodie spielen, können wir einen übereinander auswählen, aber der Unterschied ist für unsere Zwecke nicht wichtig.
Noten spielen
Wir sind bereit, ein paar Notizen zu spielen!
Erstens brauchen wir einen Weg, um zu sagen, welche Noten zu einem bestimmten Zeitpunkt gespielt werden. Lassen Sie uns dies mit der Karte tun, da die eindeutigen Schlüsselbeschränkungen uns helfen können, dass dieselbe Note in einem einzigen Druck mehrmals ausgelöst wird. Darüber hinaus können Benutzer nur auf eine Taste gleichzeitig klicken, damit wir ihn als Zeichenfolge speichern können.
<code>const pressedNotes = new Map(); let clickedKey = "";</code>
Wir brauchen zwei Funktionen, eine für die Spielschlüssel - wir werden feuern, wenn Keydown oder Mousedown - die andere zum Anhalten der Spielschlüssel - wir feuern, wenn sie KeyUp oder MouseUp.
Jeder Schlüssel spielt auf seinem eigenen Oszillator und verfügt über einen eigenen Verstärkungsknoten (zur Steuerung des Volumens) und seinen eigenen Wellenformtyp (zur Bestimmung des Klangs des Klangs). Ich habe eine Dreieckswellenform gewählt, aber Sie können jede "Sinus", "Dreieck", "gezackt" und "quadratische Welle", die Sie bevorzugen. Die Spezifikation enthält weitere Informationen zu diesen Werten.
<code>const playKey = (key) => { if (!keys[key]) { return; } const osc = audioContext.createOscillator(); const noteGainNode = audioContext.createGain(); noteGainNode.connect(audioContext.destination); noteGainNode.gain.value = 0.5; osc.connect(noteGainNode); osc.type = "triangle"; const freq = getHz(keys[key].note, (keys[key].octaveOffset || 0) 4); if (Number.isFinite(freq)) { osc.frequency.value = freq; } keys[key].element.classList.add("pressed"); pressedNotes.set(key, osc); pressedNotes.get(key).start(); };</code>
Unsere Stimme muss verbessert werden. Derzeit hat es eine leicht scharfe Mikrowellen -Summerqualität! Aber das ist genug, um zu beginnen. Wir werden wieder am Ende sein, um einige Anpassungen vorzunehmen!
Die Stopptaste ist eine einfachere Aufgabe. Wir müssen jede Notiz für eine Weile (ungefähr zwei Sekunden) "fortsetzen", nachdem der Benutzer seinen Finger gehoben und die erforderlichen visuellen Änderungen vorgenommen hat.
<code>const stopKey = (key) => { if (!keys[key]) { return; } keys[key].element.classList.remove("pressed"); const osc = pressedNotes.get(key); if (osc) { setTimeout(() => { osc.stop(); }, 2000); pressedNotes.delete(key); } };</code>
Alles, was übrig bleibt, ist, unseren Event -Hörer hinzuzufügen:
<code>document.addEventListener("keydown", (e) => { const eventKey = e.key.toUpperCase(); const key = eventKey === ";" ? "semicolon" : eventKey; if (!key || pressedNotes.get(key)) { return; } playKey(key); }); document.addEventListener("keyup", (e) => { const eventKey = e.key.toUpperCase(); const key = eventKey === ";" ? "semicolon" : eventKey; if (!key) { return; } stopKey(key); }); for (const [key, { element }] of Object.entries(keys)) { element.addEventListener("mousedown", () => { playKey(key); clickedKey = key; }); } document.addEventListener("mouseup", () => { stopKey(clickedKey); });</code>
Beachten Sie, dass die meisten unserer Ereignishörer dem HTML -Dokument hinzugefügt werden, wir jedoch das Schlüsselobjekt zum Schlüsseln verwenden können, um den Klick -Listener zu dem spezifischen Element hinzuzufügen, das wir bereits abfragt haben. Wir müssen auch eine besondere Behandlung in unseren höchsten Notizen durchführen und sicherstellen, dass wir den "Semikolon" des Schreibformulars, das wir im Schlüsselobjekt verwenden, umwandeln.
Wir können jetzt die Schlüssel auf dem Synthesizer spielen! Es gibt nur ein Problem. Der Sound ist immer noch hart! Möglicherweise möchten wir die Oktave der Tastatur senken, indem wir den Ausdruck ändern, den wir der FREQ -Konstante zuweisen:
<code>const freq = getHz(keys[key].note, (keys[key].octaveOffset || 0) 3);</code>
Möglicherweise können Sie am Anfang und am Ende des Sounds auch den Klick -Sound hören. Wir können dieses Problem lösen, indem wir jeden Sound allmählich verblassen und allmählich ausführen.
In der Musikproduktion verwenden wir den Begriff Angriff , um die Zeit zu beschreiben, die ein Sound braucht, um von still bis maximal Volumen zu gelangen, und „Release“, um zu beschreiben, die Zeit, die der Sound braucht, um zu verblassen, um zu stillen, nachdem er aufhört zu spielen. Ein weiteres nützliches Konzept ist die Abschwächung , die Zeit, die der Sound benötigt, um von Peak Volume bis kontinuierlich zu landen. Zum Glück verfügt unser Notonnode über eine Gain -Eigenschaft mit einer Methode namens ExponentialRamptovalUeatTime, mit der wir Angriffe, Veröffentlichungen und Dämpfungen kontrollieren können. Wenn wir die vorherige PlayKey -Funktion durch die folgende Funktion ersetzen, erhalten wir bessere Auswahlgeräusche:
<code>const playKey = (key) => { if (!keys[key]) { return; } const osc = audioContext.createOscillator(); const noteGainNode = audioContext.createGain(); noteGainNode.connect(audioContext.destination); const zeroGain = 0.00001; const maxGain = 0.5; const sustainedGain = 0.001; noteGainNode.gain.value = zeroGain; const setAttack = () => noteGainNode.gain.exponentialRampToValueAtTime( maxGain, audioContext.currentTime 0.01 ); const setDecay = () => noteGainNode.gain.exponentialRampToValueAtTime( sustainedGain, audioContext.currentTime 1 ); const setRelease = () => noteGainNode.gain.exponentialRampToValueAtTime( zeroGain, audioContext.currentTime 2 ); setAttack(); setDecay(); setRelease(); osc.connect(noteGainNode); osc.type = "triangle"; const freq = getHz(keys[key].note, (keys[key].octaveOffset || 0) - 1); if (Number.isFinite(freq)) { osc.frequency.value = freq; } keys[key].element.classList.add("pressed"); pressedNotes.set(key, osc); pressedNotes.get(key).start(); };</code>
Zu diesem Zeitpunkt sollten wir einen funktionierenden, netzwerkbereiteten Synthesizer haben!
Die Zahlen in unseren SetAttack-, SetDeCay- und SetRelease -Funktionen scheinen etwas zufällig zu sein, aber sie sind eigentlich nur Stiloptionen. Versuchen Sie, sie zu ändern und zu sehen, welche Änderungen am Klang aufgetreten sind. Möglicherweise erhalten Sie den Effekt, den Sie bevorzugen!
Wenn Sie daran interessiert sind, das Projekt zu fördern, können Sie es verbessern. Vielleicht ist es eine Volumensteuerung, eine Möglichkeit, zwischen Oktaven zu wechseln oder eine Möglichkeit, zwischen Wellenformen zu wählen? Wir können Hall- oder niedrige Passfilter hinzufügen. Oder kann jeder Sound aus mehreren Oszillatoren bestehen?
Für alle, die daran interessiert sind, zu verstehen, wie das Konzept der Musiktheorie im Web implementiert werden kann, empfehle ich, den Quellcode des Tonal NPM -Pakets zu betrachten.
Das obige ist der detaillierte Inhalt vonSo codieren Sie eine spielbare Synth -Tastatur. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

Video Face Swap
Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heißer Artikel

Heiße Werkzeuge

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6
Visuelle Webentwicklungstools

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen











Versuchen wir, hier einen Begriff zu prägen: "Statischer Formanbieter". Sie bringen Ihre HTML

Zu Beginn eines neuen Projekts erfolgt die SASS -Zusammenstellung im Blinzeln eines Auges. Dies fühlt sich gut an, besonders wenn es mit Browsersync kombiniert ist, das nachlädt

In der Zusammenfassung der Plattformnachrichten in dieser Woche stellt Chrome ein neues Attribut für das Laden, Zugänglichkeitspezifikationen für Webentwickler und die BBC -Bewegungen ein

Ich schaue mir das HTML -Element zum ersten Mal an. Ich habe es für eine Weile dessen bewusst, aber Haven ' Es wurde es noch nicht für einen Dreh genommen. Es hat einige ziemlich cool und

Buy or Build ist eine klassische Technologiedebatte. Das Aufbau von Dingen selbst ist vielleicht billiger, weil Ihre Kreditkartenrechnung keine Werbebuchung gibt, aber

In der Roundup in dieser Woche, einem praktischen Lesezeichen für die Inspektion von Typografie, unter Verwendung dessen, wie sich JavaScript -Module gegenseitig importieren, sowie Facebook ' s.

Für eine Weile war iTunes der große Hund im Podcasting. Wenn Sie also "Abonnieren Sie Podcast" verlinkt haben, um zu mögen:

Es gibt eine Menge Analyseplattformen, mit denen Sie Besucher- und Nutzungsdaten auf Ihren Websites verfolgen können. Vielleicht vor allem Google Analytics, das weit verbreitet ist
