Přeskočit na obsah

Audio a hudba

Dva způsoby, jak na PicoPadu vyloudit zvuk, oba přes jeho PWM audio pin. picogame_audio přehrává vzorková data (.wav soubory a generované tóny) přes mixer, takže se efekty můžou překrývat; picogame_synth generuje tóny v reálném čase přes synthio, takže celá sada SFX nestojí skoro žádnou RAM. Audio pin najdeš v /cs/hardware/ a holé signatury v /cs/reference/.

Tenká pohodlná vrstva nad audio stackem CircuitPythonu (audiopwmio + audiocore + audiomixer). Sáhni po ní, když máš .wav assety k přehrání, nebo když chceš jednoduché pípnutí bez přibalování souborů. Nastaví mixer s několika hlasy, takže výstřel, výbuch i smyčkující hudba můžou znít naráz. Výchozí hodnoty (22050 Hz, mono, 16-bit signed) odpovídají typickým ugame .wav assetům - každý vzorek, který přehráváš, musí tomuto formátu odpovídat.

Audio(pin=None, voices=4, sample_rate=22050, channels=1, bits=16, signed=True)

Sekce “Audio(pin=None, voices=4, sample_rate=22050, channels=1, bits=16, signed=True)”

Sestaví audio výstup a okamžitě spustí mixer. pin=None použije board.AUDIO. voices je počet souběžných kanálů; hlas 0 je vyhrazený pro hudbu a hlasy 1..N-1 se používají round-robin pro zvukové efekty. Ostatní argumenty definují formát vzorku, kterému musí každý klip odpovídat.

  • load(path) - otevře .wav soubor jako znovupoužitelný WaveFile vzorek. Postav ho jednou a vrácený objekt drž naživu (drží otevřený soubor); přehrát ho znovu je levné.
  • play(sample, *, voice=None, loop=False, volume=1.0) - přehraje vzorek. voice je keyword-only; None vybere další round-robin sfx hlas. volume nastaví hlasitost toho hlasu (0.0-1.0). Vrátí index hlasu, který použil.
  • sfx(sample, volume=1.0) - efekt typu fire-and-forget na volném sfx hlasu (volá play s loop=False). Vrátí index hlasu.
  • music(sample, loop=True, volume=1.0) - přehraje na vyhrazeném hudebním hlasu (hlas 0), ve výchozím stavu ve smyčce.
  • stop(voice=None) - zastaví jeden hlas, nebo všechny hlasy, pokud je voice None.
  • stop_music() - zastaví jen hudební hlas.
  • is_playing (vlastnost) - True, pokud zrovna hraje nějaký hlas.
  • deinit() - uvolní audio výstup. PWM pin board.AUDIO je singleton, takže tohle zavolej před vytvořením druhého Audio() - jinak další Audio() vyhodí pin in use.

tone(frequency=440, ms=120, sample_rate=22050, volume=0.6)

Sekce “tone(frequency=440, ms=120, sample_rate=22050, volume=0.6)”

Sestaví v RAM krátký RawSample s pravoúhlou vlnou - pípnutí bez potřeby .wav souboru. Hodí se na prototypování a jednoduché blikance. Výsledek odpovídá mono 16-bit signed mixeru, takže ho můžeš předat rovnou do sfx/play.

import picogame_audio
import picogame_input
audio = picogame_audio.Audio() # PWM audio, 4 voices
pew = picogame_audio.tone(880, 90) # high blip, built once
boom = picogame_audio.tone(140, 200) # low thud
btns = picogame_input.Buttons()
while True:
btns.poll()
if btns.just_pressed(btns.A):
audio.sfx(pew) # overlaps on a free voice
if btns.just_pressed(btns.B):
audio.sfx(boom, volume=0.8)

Záludnosti:

  • Každý vzorek musí odpovídat formátu mixeru. .wav se 44100 Hz nebo stereo se přehraje špatně (nebo vyhodí chybu); assety si nejdřív převzorkuj na 22050 Hz mono 16-bit.
  • Výsledky load() drž naživu - když se WaveFile posbírá garbage collectorem, otevřený soubor jde s ním. Klipy načti jednou při startu, ne každý frame.
  • Máš jen voices-1 sfx kanálů; rychle za sebou jdoucí efekty se točí round-robin a jakmile se přetočí, začnou se navzájem uřezávat.

Syntéza v reálném čase přes synthio - oscilátory, ADSR obálky, pitch-bend LFO a low-pass filtry, bez jakýchkoli vzorkových bufferů. Sáhni po ní, když chceš bohatou sadu SFX nebo hudbu na pozadí, ale nemůžeš si dovolit RAM (nebo soubory s assety), kterou WAV vzorky potřebují. Obaluje řetězec PWM-out -> mixer -> synthesizer a přináší vestavěné průběhy. Tohle je modul jen pro zařízení: synthio v simulátoru není, takže import ošetři podmínkou nebo ho spouštěj jen na hardwaru. Pokud chceš místo toho přehrávat vzorky, použij picogame_audio výše; v /cs/memory/ najdeš, proč na úspoře RAM záleží.

Vestavěné konstanty průběhů (jednocyklová, signed 16-bit pole, která sdílíš mezi notami): SINE, SAW, TRIANGLE, SQUARE, NOISE. Funkce sine(), saw(), triangle(), square(), noise() postaví čerstvé kopie, pokud je potřebuješ.

note(midi, waveform=None, attack=0.005, decay=0.06, sustain=0.0, release=0.08, amplitude=0.6, bend=None, cutoff=None)

Sekce “note(midi, waveform=None, attack=0.005, decay=0.06, sustain=0.0, release=0.08, amplitude=0.6, bend=None, cutoff=None)”

Sestaví znovupoužitelnou notu/SFX/nástroj - základní stavební kámen. midi je číslo MIDI noty (60 = komorní C, 72 = C5). waveform je jedna z konstant výše. attack/decay/sustain/release tvarují ADSR obálku v sekundách (krátký decay se sustain=0.0 dá perkusivní blikanec). amplitude je hlasitost (0.0-1.0). bend bere pitch_bend LFO pro skluz; cutoff přidá low-pass filtr na daném počtu Hz, aby zaoblil drsné tóny. Každou notu postav jednou a přehrávej znovu.

pitch_bend(semitones, ms, waveform=None, once=True)

Sekce “pitch_bend(semitones, ms, waveform=None, once=True)”

Vrátí synthio.LFO vhodný pro bend noty - sklouzne výšku o semitones během ms milisekund. Použij kladnou hodnotu pro stoupavý zvuk, zápornou pro klesavý pád. S once=True proběhne skluz jen jednou při každém spuštění.

Synth(pin=None, sample_rate=22050, buffer_size=2048, music_level=0.4, sfx_level=0.7)

Sekce “Synth(pin=None, sample_rate=22050, buffer_size=2048, music_level=0.4, sfx_level=0.7)”

Nastaví PWM výstup a 2hlasý mixer: hlas 0 pro hudbu (MidiTrack), hlas 1 pro živý synth používaný pro SFX. pin=None použije board.AUDIO. music_level/sfx_level jsou počáteční úrovně mixu pro tyto dva hlasy.

  • sfx(n) - přehraje notu n jako jednorázový efekt. Nejdřív znovu spustí LFO té noty (aby opakovaný zvuk zněl pokaždé stejně), pak zavolá release_all_then_press, takže SFX jdoucí těsně za sebou se uříznou čistě.
  • press(n) / release(n) - podrž a uvolni notu ručně, pro zvuky, které trvají tak dlouho, dokud držíš tlačítko, místo aby cvakly jednou.
  • music(midi_track) - přehraje MidiTrack (z load_midi) na hlasu 0, ve smyčce.
  • stop_music() - zastaví hudební hlas.

load_midi(path, sample_rate=22050, waveform=None, envelope=None, tempo=120, ppqn=240)

Sekce “load_midi(path, sample_rate=22050, waveform=None, envelope=None, tempo=120, ppqn=240)”

Načte .mid soubor jako synthio.MidiTrack, který předáš do Synth.music. waveform a envelope vyberou hlas nástroje pro celou stopu; tempo (BPM) a ppqn nastaví rychlost přehrávání. Automaticky přeskočí standardní hlavičku format-0 SMF, takže obyčejné exportované MIDI prostě funguje.

import picogame_synth as snd
import picogame_input
s = snd.Synth()
# Each SFX is a Note built ONCE (envelope + optional bend + filter).
blip = snd.note(72, snd.SQUARE, decay=0.10)
zap = snd.note(60, snd.SAW, decay=0.18, cutoff=4000, bend=snd.pitch_bend(12, 180))
boom = snd.note(45, snd.NOISE, attack=0.0, decay=0.30, amplitude=0.55, cutoff=2800)
btn = picogame_input.Buttons()
while True:
btn.poll()
if btn.just_pressed(btn.A):
s.sfx(zap)

Záludnosti:

  • Jen pro zařízení - synthio v simulátoru chybí. picogame_synth importuj uvnitř if/try nebo jen na skutečném hardwaru, tak jak to dělají příklady train a dinorun.
  • Každou note() postav jednou při startu a přehrávej znovu; sfx se o znovuspuštění postará. Přestavovat noty každý frame mrhá časem a rozbíjí znovuspuštění LFO.
  • Zvuk vydává synthesizer, ne objekt noty - efekty hrají jen přes živý Synth a hlasy mixeru jsou jen dva (jeden hudba, jeden SFX), takže překrývající se synth SFX sdílejí jediný hlas.