Budowanie silnika audio od podstaw to rytuał przejścia. Chcesz zrozumieć generator zegara. Chronometraż. Surowa logika, która zamienia ciszę w rytm. Sekwenser jest tą logiką. To jest siatka. Umieszczasz notatki. Idziesz do przodu.
Większość przewodników pomija najtrudniejszą część. Pokazują ci bibliotekę. Pokazują ci GUI. Nie pokazują, jak radzić sobie z driftem. Błędy pomiaru czasu, które kumulują się podczas ręcznego śledzenia czasu.
Naprawmy to.
Tworzymy podstawowy sekwencer kroków. Będzie działać w prostej pętli. Będzie odtwarzać dźwięki. Utrzyma rytm, nie patrząc przed siebie. Takie podejście zapobiega odczuciu „szarpnięcia”, które pojawia się podczas używania parametru „setTimeout” do długich pętli.
Podstawowa koncepcja: synchronizacja kroków
Sekwenser działa etapowo. Nie przez sekundy. Na schodach.
Jeśli Twoje tempo wynosi 120 uderzeń na minutę (BPM), każde uderzenie trwa 0,5 sekundy. Jeśli masz 16 kroków, każdy krok trwa 0,125 sekundy. Magia dzieje się, gdy synchronizujesz te interwały.
“Czas w sekwencerze nie jest ciągłym strumieniem. To seria odrębnych zdarzeń. Synchronizacja z tymi zdarzeniami jest wszystkim.”
Potrzebujemy sposobu na obliczenie, kiedy następuje każdy krok. Nie przez zgadywanie. Poprzez matematykę.
Konfigurowanie generatora zegara
Potrzebujesz punktu wyjścia. Czas rozpoczęcia.
W JavaScript „Date.now()” lub „ Performance.now()” zwraca milisekundy. Używasz tego do obliczenia dryfu.
- Określ tempo.
- Oblicz czas trwania kroku.
- Rozpocznij cykl.
Oto szkielet kodu. Nie jest zbyt przystojny. Ale to działa.
Ten kod jest podstawowy. Używa setTimeout. Nie jest idealny. Ale to jest początek.
Dlaczego to jest ważne?
Po co tworzyć to sam?
Biblioteki takie jak Tone.js lub opakowania dla Web Audio API są świetne. Zajmują się złożonym planowaniem. Rekompensują opóźnienia.
Ale nie dowiesz się, jak działają, po prostu ich używając. Uczysz się, obserwując, gdzie zawiodły.
Kiedy setTimeout dryfuje, twój bit się zmienia. To brzmi po ludzku. To nie brzmi dobrze.
Przetwarzanie dryfu
Sprawdzenie if (nextStepTime < Date.now()) jest krytyczne.
Ona























