Když jsem se v roce 1992 prvně setkal s Amigou 500+, byl jsem unesený ze všeho, co Amiga nabízela. Kdo zažil uvěří. Hry byly super, ale demoscéna, to je pojem. Demoscénu sleduji a kroužím kolem již několik let. Dema vnímám jako prostředek, jak ostatním ukázat, co s daným počítačem dokážu. Dema jsou pasivní aplikace, které nevyžadují uživatelovu interakci. Vizuální a audio část je spolu spojena a navzájem se doprovází. Vhodné načasování pak vytváří dokonalý dojem. Dema vytváří často tvůrčí skupinky, kde je práce rozdělena. Často se pak stává, že grafickou podobu dělá jeden člověk a my pak můžeme ohodnotit, jak pěkně umí grafiku. Jiný programuje 3D engine a my se můžeme kochat pohybem oživlé grafiky a samozřejmě muzikant, který skládá hudbu pro dané demo. Přiznám se, že mým oblýbeným hudebním autorem ve spojení s fenoménem Amiga jsou: Travolta Spaceballs, Laxity, Jogeir Liljedahl.
Jak jsem naznačil, vizuální a audio spojení pak může přinášet hluboké dojmy a je to ideální způsob, jak dovednosti prezentovat.
Navíc, pokud demo sleduje někdo z oboru, dokáže si přestavit náročnost, která za zrovna sledovanou scénou probíhá.
Hudební formát MOD byl dlouhá léta oblíbeným formátem všech borců, kteří dema tvořili a stále tvoří. Nějaký pátek jsem strávil za obrazovkou ProTrackeru na Amize 1200 a později u FastTrackeru a Scale na PC. Já nemám dar skládat libou muziku, ale muziku rád poslouchám a jako technicky orientovanému člověku mi formát MOD očaroval. S oblibou jsem remixoval mé oblíbené skladby a tešil se z toho, jak se dá snadno na počítači tvořit hudba.
Ukázka sama za sebe, jedno z nejznámějších dem pro Amigu A500, informace o harware si můžete zjistit na internetu. Demo je z roku 1993
(Videa nejsou má, přijde mi zbyterčné grabovat to, co na youtubu již je)
Desert Dream Část 1.
Desert Dream Část 2.
Obdivoval sem a stále obdivuji tu nadčasovost, kterou tento hudební formát od svých autorů získal. Tímto bych rád smeknul a složil poklonu pánům Karsten Obarskimu, který formát stvořil a Mahonymu a Kaktusovi, kteří se významně podepsali na rozvoji tohoto formátu. A také všem, kdo zvládli vlastní implementaci, protože to není zrovna triviální záležitost, i když formát souboru je elegatně přehledný.
Na amigách bylo postavení přehrávače o něco jednodušší, protože například samply, digitální vzorky hudebních nástrojů, jsou v modulech ukládány ve formátu 8-bit PCM, což je identický formát, s jakým pracuje DAC chip Amigy. Takže tamní programátoři nemuseli řešit trasformace a konverze. To je také důvod, proč přehrávátka na Amigách braly zlomky výkonu CPU.
Vetšinou mi nestačí pouze vědět, jak věci fungují, ale mám často potřebu to umět i naprogramovat. Někdy v roce 2001 jsem se rozhodl, že si naprogramuji vlastní přehrávátko na "moduly" pod Windows.
Věděl jsem o problematice hodně věcí, měl jsem k dispozici popisky jak formátu souboru, tak i některé implementační teorie pro Amigy.
Dalším důvodem, proč jsem se rozhodl napsat si vlastní přehrávátko, byla i ona demoscéna, do které jak pevně doufám ještě přispěji. Prostě jsem nechtěl použít "cizí" kód, ale jen vlastní. Časem napíši povídání o tom, jak jsem zkoušel jednoduchou 3D grafiku pomocí GDI :)
Pro vývoj jsem zvolil Delphi, protože jsem je v té době aktivně používal. I dnes v nich sem tam něco ještě napíšu. Většinou po nich sáhnu, když potřebuji nějakou utilitu a honem rychle. Delphi ovládám dobře a tak většinou nemusím zkoumat technologické temné kouty, jak říkává jeden můj kolega.
Vybral jsem z archivu modulů ty pro mě nejzajímavější, ty které se mi nejvíc líbily a prohlásil jsem je za takový "unit test". Prostě když tyhle moduly dokážu přehrát pokud možno identicky jako Amiga, budu spokojený.
Vybral jsem tyto moduly:
(ke stažení zde)
Později, abych nemusel používat emulátor na Amigu pro přehrávání modulů, začal jsem používat stařičký WinAMP 2.9, který umí moduly také přehrávat a to celkem slušně. Tato stará verze se dá stále stáhnout. Je to maličkýá přehrávač a hraje dobře, dDodnes ho používám pro přehrávání MP3.
Přehrávátko je nyní ve třetí generaci. Dvě předchozí generace jsem zahodil, protože jsem se vydal špatnou a slepou cestou. Zprvu jsem neuměl mixovat zvuky dohromady a tak jsem hledal způsoby, jak přehrát paralelně dva a více zvuků najednou.
Zkoušel jsem to přes DirectSound, zkoušel jsem to přes vlákna. Ani jedna varianta nefungovala tak, jak jsem si představoval. Spouštění samplů v jednom momentě mi nefungovalo přesně a také jsem měl potíže s opakováním samplů. Pokud byl sample opakovaný, nedařilo se mi včas nastavovat jeho novou pozici na začátek offsetu opakování. Dojem z takové muziky byl dle mého názoru mizerný.
Třetí generace již mixuje jednotlivé samply dohromady v jeden výstupní a výsledný zvuk. K přehrávání jsem použil nekonečný audio stream. Toto je velice elegantní způsob, jak pořešit všechny potíže, které jsem v předchozích generacích projektu měl anebo vytvořil.
Princip je velice jednoduchý. Otevře se pomoci Win32 API waveOutOpen audio výstup ve specifikovaném formátu a také se definuje callback funkce, kterou bude systém volat, aby fukce obsloužila zprávy, které při přehrávání nastanou. Pomocí API waveOutWrite zapíši do audio streamu připravená hudební data. A v tom je ta krása. Callback funkce je volána v případě, že se blíží konec přehrávaného bufferu a je tedy potřeba namixovat další kus výstupního zvuku.
Celý přehrávač tedy funguje v režimu, kdy chviličku pracuje naplno a mixuje samply a pak je v klidu a nic nedělá. V tu dobu, kdy nic nedělá, přehrává systém data, která program namixoval. Ve chvíli, kdy namixovaná data dochází, zavolá systém callback a tím se opět spustí další cyklus přehrávátka. Opět namixuje další kus muziky a čeká až se data přehrají. Délka zvukového záznamu, který se vytváří, mixuje a následně přehrává se definuje při otevírání audio kanálu. Čím menší je buffer pro přehrávaná data, tím častěji je callback volaný, ale také lze spíše reagovat na podněty zvenčí. Například změna hlasitosti uživatelem. Nebo když bych chtěl vyvolávat nějakou událost pokaždé, když přehrávátko přehraje vybraný nástroj, bylo by dobré aby buffer byl co nejkratší. Kdyby byl buffer naopak dlouhý, nebyly by reakce formou event dobře načasované a to právě díky tomu, že se dopředu vytvoří například 10 vteřin muziky a pak se 10 vteřin z pohledu aplikace nic neděje.
Jak je vidět, celý mechanizmus je celkem jednoduchý, pokud si srovnáme v hlavě, jak to pracuje po kusech. Implementace mechanizmu je v podstatě také jednoduchá. Co je ale složitější, je právě ono mixování všech těch nástrojů dohromady. Aplikace v současné verzi nastavuje kvalitu výstupního zvuku pomocí kompilačních direktiv. To znamená, že za běhu programu nelze měnit kvalitu výstupu. Je to kvůli rozdílným datovým typům. Pokud bude výstup 8bitový, pracuje i mixovaci mechanizmus 8bitově a proměnné, které k tomu používá jsou také 8bitové. Analogicky je to u 16bitové kvality zvuku. Musel bych mít dva mechanizmy, abych obsloužil tak rozdílné typy proměnných. Je otázka co je menší zlo. Jestli dvě podobné metody anebo jednu metodu prošpikovanou kompilačními direktivami. Pro potřeby doprovodné muziky pro nějakou grafickou scénu jsou ale kompilační direktivy správné řešení, protože za běhu aplikace nebudu mít potřebu volit si kvalitu výstupu, ale ještě použiji tu, kterou nastavím já v době vývoje. Celé se to ale stává složitějším ještě samplovací frekvencí, která může být libovolná z těch, které systém podporuje. Běžně se používají frekvence 11025Hz, 22050Hz a 44100Hz. Zde je největší problém v tom, že většina samplů, které jsou v modulech uložené jsou 8bitové a vzorkované na 22KHz. Dále výstup může být mono, stereo nebo pseudo surround.
Mixovací metoda s tímto vším musí pracovat a data samplů upravovat. Tomu se říká resamplování a děje se to za běhu. Vytvořím rozdílový koeficient výstupní frekvence a vstupní frekvence každého samplu. Tento koeficient pak používám k vyčítání dat samplu tak, že data samplu přeskakuji v případě, že je sample kvalitnější než audio výstup a nebo data opakuji v opačném případě. Pokud je frekvence shodná, dochází k přímému kopírování. Až nahlédnete do zdrojového kódu, uvidíte, že je to ještě malinko zamotanější, ale naštěstí pochopitelné. Do série zpracování výstupního zvuku jsem ještě začlenil úpravu výstupu pomocí jednoduchého tří-pásmového ekvalizéru. Je tak možné řídit basy, středy a výšky. Pomocí tohoto ekvalizéru lze získat celkem pěkné výsledky.
Teď, když je popsán mixovací mechanizmus, je na řadě popsat lehce formát modulu a vysvětlit, jak mixování samplů ve výslednou muziku vlastně probíhá. Popisuji to proto, že z implementačního hlediska se jedná o celkem slušnou výzvu.
O formátu modulu se lze na internetu v současnosti dočíst snad úplně vše.
Mohu doporučit stručný, ale výstižný popis na WiKi zde.
Existují různé variace, avšak ta nejrozšířenější variace s označením M.K. (Mahoney and Kaktus) říká, že:
Dále specifikace říká, že rychlost, jakou se přehrávátko pohybuje z jedné řádky matice na druhou, je definována pomocí BPM (beats per minute). Standardní hodnota je 125 BPM. Další významná informace je, že mezi přechodem z jednoho řádku na druhý se může několikrát aktualizovat efekt. Počet je definován jako Speed a standardní hodnota je 6. Další pojem je Tick, který představuje pohyb v rámci jedné řádky a to v rozsahu 1 až Speed.
Efekty se rozdělují na 2 základní skupiny a to:
Pomocí tickových efektů se dosahuje například vibráta, zkrácení hrací doby samplu. Přechod z jedné noty na druhou (frekvenční přechod po tónech nebo půltónech, a další).
Zde je výpis efektů, které přehrávátko v současnosti implementuje a jen stručně popis (samotná implementace některých efektů je náročná stejně jako složitost jejich detailniho popisu, který ale neuvádím):
Krátké vysvětlení označení efektů pro lepší přestavení:
1. písmeno je označení efektu
x a y jsou volitelné parametry ovlivňující algoritmy efektů, x a y jsou 4-bitová čísla, někdy se použivají jako jedno 8-bitové číslo a někdy se dělí po 2 bitech.
Tak, jak to říci jednoduše. Skoro bych zápis modulu přirovnal k jazyku, definujícímu přehrávání muziky. Něco jako hudební programovací jazyk. Nicméně každý si dokáže přestavit, že skladatel musel znát mnoho technických detailů jak o hudbě, tak především o způsobu interpretace efektů. Ticks, Speed a BPM spolu s parametry x a y jako parametry do algoritmů. Nic snadného.
Je řada modulů, kde se používají jen ty nejzákladnější efekty, ale pak je řada těch hodně vypilovaných, kde je vidět a hlavně slyšet, že autor je prostě a jednoduše borec.
Například jeden takový borec je Laxity, programuje a zároveň skládá muziku, tím že si sám programuje hudební interpreter přesně ví, jak efekty dobře využít. Mrkněte na následující video, ukazující přehrávání modulu Desert Dream #2 v ProTrackeru na Amize. Je vidět komplexnost a složitost modulu.
Nebo zde jiný příklad objemu dat, od 2:24
Když jsem ladil frekvenční tabulky a některé efekty, moje žena si se mnou vyloženě užila. Jí se éra Amig nedotkla a většina skladeb jí připadá příliš syntetických. Když jsem ladil efekty, stavěl jsem si ukázkové moduly, kde jsem mohl sledovat jak je implementace přesná v porovnání například se zmíněným ProTrackerem nebo WinAMPem. To bylo falešných zvuků a chrčení, když mi ukazatelé v mixéru ujely do jiné paměti. Od té doby tomu žena neříká přehrávátko, ale pípátko. Ladění trvalo poměrně dlouho. Jednak se k tomuto projektu vracím průběžně a druhak zde bylo spousty pro mě nových mechanizmů a také ladění tohoto typu aplikace je časově náročné.
Pro mně to ale byl fajn strávený čas a získání dalších skillů navíc. Na linkedIn si tohle do profesního životopisu dát nemůžu, ale ruku na srdce. Pro mě je zajímavější psát taková pípátka, než kdo ví kolika vrstvé systémy které přehazují data z jené strany na druhou. Občas je ta profesní práce také zábavná, zejména pokud mohu prokopnout nové věci, nové směry nebo nové technologie, ale tohle, tohle je zajímavější.
Naprogramoval jsem přehrávátko, které má následující rysy:
Ještě krátký příběh k formátu UNIC. Kdo zná demo Desert Dream z Amigy ví, že v demu byla skrytá část, Tam byla taková jemná muzika od Laxity. Nedařilo se mi tento modul vůbec vygooglit. Jen na jednom místě v tom obrovském houští internetu jsem ho našel, ale ve formátu UNIC. Do té doby jsem o tomto formátu vůbec nevěděl. Ve své podstatě je to téměř stejný format jako typycký MOD, jen jsou některé informace jinak interpretovány. Obocně se takto autoři chránili proto, aby nějaký šikula s ripperem nevykuchal muziku jen tak jedním kliknutím.
Zdrojové kódy jsou přeložitelné pod Turbo Delphi, Delphi 2005 (nepodstatné rozdíly v DFM), Delphi 2006. Protože nepoužívám žádné featury, které jsou jen v některých verzích, půjde to přeložit od Delphi3 až po poslední verze Delphi, nejspíš. Možná některé vlastnosti vizuálních komponent nejsou ve všech verzích Delphi.
Zdrojové kódy jsou zde.
(Používejte dle libosti. Pokud použijete, dejte mi jen vědět a případně mě uveďte do credits vašeho projektu).
Komentáře unity "UModProcess.pas" jsou poměrně masivní a lze je číst jako další článek, tentokáte ale plný technických detailů.
Pár slov a demo aplikaci kterou si můžet stáhnout z odkazu výše a je vidět na screen shotu výše:
Demo aplikace má za úkol demonstrovat jak se přehrávátko používá. Vytvoří se instance přehrávače, zavolá se metoda pro nahrátí hudebního modulu a pomocí zavolání metody Play to začne hrát. Demo aplikace také zobrazuje průběh přehrávání. Posun ale není přesný, protože to jde proti principu mixování audio výstupu dopředu. Proto na otázku, jak to fuguje, odpovím, že: V unitě UModProcess.pas na řádku 2261 je tento kód "XNumSamples := XSamplesPerBeat * FSpeed div 2;" a řáká, kolik dat se o výstupního bufferu mixuje. Stačí buffer zvtšit a sníží se frekvence callbacků.
Demo aplikace má tlačítko "Load Module", které nahrává moduly z disku PC. Tlačítka "RES MOD" a "RES UNIC" nahrávají moduly z resource aplikace. Jeen ve formátu MOD a druhý v UNIC. Tlačítka "Play" a "Stop" jsou jasná.
Posuvníkem Volume, lze měnit hlasitost. A Ekvalizér má funkci také jasnou. Račte ozkoušet.
Jako obvykle, žádný software není dokonalý a tak mi prosím odpusťte chyby, které najdete.
No a proč zveřejňuji tyto zdroje? Jenoduše proto, že se to třeba může někomu hodit a nebo proto, že jsem chtěl ostatním říci čím se také dále zabývám a čím si vyplňuji volný čas, kterého je čím dál méně. Třeba v mých zdrojácích najdete inspiraci, zkušenosti a nejspíš také chyby.
Zde bych chtěl také poděkovat Neilu C., jehož zdoje pro ekvalizér jsem použil, přeložil do Delphi a lehce modifikoval.
Dále děkuji všem, kdo píší na web specifikace a zveřejňují zdroje, páč tak ostatní mají možnost něco okoukat, vylepšit.