int21h

Zvuky v Turbo Pascalu 7

Zatím poslední článek o něčem (!), který mne napadl, se bude věnovat zvukům a hudbě na počítači. Ukážeme si, že obsluha zvukové karty je v podstatě velmi jednoduchá činnost. Budeme se věnovat hlavně obsluze karet v DOSových aplikacích, takže vynecháme různé FMOD a BASS knihovny, SDL, atd., které umí totéž např. i ve Windows, Linuxu, atd. a jsou většinou určeny hlavně pro Free Pascal.

Hlavním předpokladem je dobře nakonfigurovaná karta. Pokud běžíte pod čistým DOSem, musíte mít v paměti jednak ovladač (většinou EXE program), a v ideálním případě ještě dobře nastavenou proměnnou BLASTER, kde se určuje přerušení IRQ (5,7), DMA (většinou 1 či 3), 16 bitové DMA (5), adresa MIDI (330, atd.), typ karty, a bázová adresa (220h, atd.), která může vypadat v AUTOEXEC.BAT nějak takto:


SET BLASTER=A220 I5 D1 H7 P330 T4  

Pokud běžíte ve Windows, můžete stejně psát program pro DOS s využitím zvukové karty. Je ale nutné počítat s tím, že buď musí karta přímo běžet na IRQ 5 a podobném (většina dnešních integrovaných), nebo musí používat tzv. Legacy ovladač (např. SB128). Na některých počítačích, kde jsou ještě karty ISA, může navíc WaveTable syntéza pro MIDI způsobovat trhání a zpomalování zvuků v DOSových hrách. Většina dnešních zvukových karet dokáže přehrávat v DOSu zvuky v kvalitě 44 kHz 8 bitů stereo. Pokud chcete 16 bitové zvuky, potřebujete kartu, která je plně kompatibilní se Sound Blaster 16 (nebo SB16 samotný). Např. kompatibilita s SBPro Vám stačit nebude a tedy Vám 16 bitové DMA nebude stejně fungovat. Ovladač ve Windows totiž nepracuje v kompatibilním módu, ale přímo se speciální funkcí dané karty a tedy 16 bitový zvuk umí, zatímco Vám ho neposkytne. Řešením může být využití emulátoru DOSBox.

Formát zvuku RAW

Než přejdeme přímo na zvukové karty, řekneme si něco o datech, která do nich můžeme posílat. Nic nám samozřejmě nebrání, abychom si vymysleli vlastní formáty stejně jako u videa a obrázků (ovšem pouze pro soubory na disku, do karty nemůžeme poslat, co chceme), ale pravděpodobně budeme stejně potřebovat číst již vytvořené zvuky od jiných autorů (pozor na legálnost věci). Základním zvukovým formátem je RAW. Ten neobsahuje žádnou hlavičku, takže sice ušetříte nějakých 50 bytů a nemusíte složitě zjišťovat, jak moc je dlouhá (takže jeho čtení je snadné), avšak zase musíte přesně vědět, v jaké kvalitě jsou uložená data (stejně jako u RAW obrázků, kdy musíte znát rozměry a BPP). Hlavním kritériem pro čtení je bitáž a počet kanálů. Daná frekvence pouze určuje rychlost čtení a délku souboru, nikoliv strukturu dat.

Zvuky mohou mít frekvenci libovolnou, ale standardně se používá 11025 Hz, 22050 Hz, 44100 Hz a někdy i 48000 Hz (u DVD až 96000 Hz). To udává, kolik vzorků je nutné přečíst a přehrát na 1 vteřinu. Formát vzorku se pak liší podle toho, zda je zvuk mono (1 kanál), stereo (2 kanály, levý+pravý, popř. ještě informace o kódování Dolby ProLogic pro 4 kanály L,R,C a 1 zadní), a zda je 1 vzorek pro každý kanál 8 bitový nebo 16 bitový. Každý vzorek pak vypadá následovně:


8 bitů mono:		B
8 bitů stereo:		L R
16 bitů mono:		L(lo) L(hi)
16 bitů stereo:		L(lo) L(hi) R(lo) R(hi)  

Kde každý údaj (B, L, R) představuje 1 byte. Velikost vzorku tedy bude 1-4 byty. Velikost 1 vteřiny zvuku pak podle frekvence může být 11025 bytů až 176400 bytů v případě kvality CD.

Dále je nutné vědět, jak jsou uložena záporná čísla. Každý byte totiž představuje určitou část sinusové vlny, která má hodnotu -128 až 128 v případě 8 bitů, či -32768 až +32767 v případě 16 bitů. Existují tři typy čísel: signed (se znaménkem), u nichž je použit pro ukládání čísel dvojkový doplněk (tj. čísla od -MIN do +MAX jdou v případě 8 bitů takto: $80-$ff,0,1-127), unsigned = bez znaménka (0-127,128,129-255), a se znaménkovým bitem ($ff-$80,0,1-$7f; with sign bit). Standardně se pro 8 bitové zvuky používá unsigned (BYTE) a pro 16 bitové signed (INTEGER). Jedná se samozřejmě o tzv. kódování PCM (bez komprese). Doporučuji se porozhlédnout na Internetu po nějaké dokumentaci.


Hlavička formátu WAV

Pokud potřebujete načítat zvuky, u nichž předem neznáte kvalitu zvuku (a tedy si neulehčíte práci při načítání RAW, kde víte, že všechna data můžete rovnou poslat do zvukové karty), musíte použít formát WAV (nebo i VOC, pokud chcete, ale to už si budete muset najít sami). Soubor WAV ukládá data stejně jako formát RAW, jen obsahuje na začátku jistou hlavičku, která poskytuje informace o zvuku (budeme se věnovat jen zvuku PCM, nikoliv ADPCM, který poskytuje 2,3 nebo 4 bitovou kompresi zvuku). Hlavička má několik pevných a několiv proměnných částí. Její začátek vypadá takto:


var	WAVhlav : record
		   Znacka : array[0..3] of char;
		   VelikostZbytku : longint;
		   NazevFormatu : array[0..3] of char;
		   Blok1 : array[0..3] of char;
		   VelBloku : longint;
		   Komprese : word;
		   Kanalu : word;
		   Frekvence : longint;
		   BytuZaSec : longint;
		   Zarovnani : word;
		   BituNaVzorek : word;
		  end;  

V této části najedete postupně tyto informace: první jsou znaky 'RIFF', pak je velikost zbytku souboru v bytech (tj. FileSize - 8 bytů), následují 4 znaky 'WAVE', a pak 3 znaky 'fmt ' s mezerou. Další údaj je velikost bloku hlavičky. Pro PCM zde najdete 16 až 18, pro ADPCM 50 bytů. Následuje informace o kompresi: PCM zde bude mít 1, ADPCM od Microsoftu 2, od IMA 17. Počet kanálů může být 1 nebo 2 (nic Vám nebrání uložit si jich kolik chcete, ale pak daný WAVe zřejmě nepřečtou "standardní" programy). Vzorkování je frekvence (stejně jako WAV, i zvukové karty umí libovolnou frekvenci, takže např. i 9500 Hz je správně, ale pokud budete mít zvuky uložené v různé frekvenci, budete muset kartu nastavit pouze na 1 a ty ostatní pak převádět, což jde dělat snadno mezi 11025, 22050, atd., ale už ne mezi náhodnými čísly jako je 9500 Hz, takže se nedoporučuje používat je). Bytů za vteřinu je vlastně údaj Frekvence*Kanalu*Bitu/8 (viz. dále). Zarovnání je velikost jednoho samplu, čili Kanalu*Bitu/8 (u ADPCM udává velikost komprimovaného bloku, tj. 32 až 1024 bytů; tady může být počet bytů za vteřinu roven např. 22 311, a to i pro 22 kHz). A poslední údaj je počet bitů na vzorek, tj. 8 nebo 16 (ADPCM zde může mít 4). Pokud je velikost bloku hlavičky větší než 16 bytů, následuje za ní ještě další blok, který je nutný přečíst:


var	WAVextra : record
		    ExtraParametru : word;
		    Parametry : array[0..31] of byte;
		   end;  

Načtěte tedy údaj o velikosti 16 bitů a podle čísla, které bude v něm, načtěte ještě dalších 0 až 32 bytů (ano, opravdu tam sice může být číslo, ale už žádné další parametry). Nyní se to může lišit. Musíme načíst nejprve 4 byty (znaky), podle kterých poznáme, s čím máte tu čest. Pokud jsou znaky rovné sekvenci 'fact', budeme mít tuto hlavičku:


var	WAVfact : record
		   Blok : array[0..3] of char;
		   PocetParam : longint;
		   Parametry : array[0..7] of byte;
		  end;  

Kde první 4 znaky budou ty FACT, pak nám počet parametrů udává, kolik bytů ještě musíme načíst. Maximální počet bytů je 8. Tyto informace většinou používá ADPCM komprese (stejně jako Extra parametry), nebo nějaké editory pro uložení informací. Pokud jsou ovšem první 4 znaky rovné 'data', bude hlavička jiná. Pokud to bylo 'fact', bude hlavička pro 'data' hned po té 'fact' hlavičce:


var	WAVdata : record
		   Blok : array[0..3] of char;
		   VelDat : longint;
		  end;  

Zde se jen dozvíte, kolik bytů zvukových dat je uloženo za hlavičkou. Pokud jste si všimli podobnosti obou hlaviček, můžete načíst nejprve 8 bytů, a pokud bude v Blok jméno 'fact', dočtete další parametry a pak znovu hlavičku 'data', v opačném případě zpracujete hlavičku už přímo jako 'data'. Většinou jsou byty až do konce souboru zvuková data, ale občas se zde mohou ještě vyskytovat (na konci souboru) bloky 'LIST' nebo 'smpl', kde je např. Copyright, atd.


Formáty ADPCM WAV, MP3, MIDI a MOD/S3M/IT

K souborům WAVe komprimovaných pomocí ADPCM existuje bohužel docela málo dokumentace. Zvukové karty sice mohou mít režim, kdy jim pošlete zvuky ADPCM a ony je přehrají, ale v tom případě musíte mít v této kompresi všechny zvuky a pokud nevíte, jak vypadá, nemůžete je mixovat, měnit hlasitost, atd. Formát ADPCM je vytvářen tak, že kompresor vždy porovnává rozdíly dvou vzorků a u těch nejrozšířenějších si vytvoří tabulku. V každém bloku dat je vždy určitý krok a pro každý sampl se používají až 4 bity pro ukazatel do dané tabulky. Pokud se pak číslo v tabulce vynásobí daným krokem, dostaneme už nekomprimovaný údaj. Jednodušší je ale vymyslet si vlastní zvukový formát, který bude např. používat 4 bitové vzorky, kde bude už přímo rozdíl bez nějakého kroku nebo použít proměnnou velikost vzorku. Viz. např. moje homepage.

Formát MP3 je velice složitý, jelikož používá proměnnou velikost rozdílu. Funguje tak, že neukládá celé vzorky, ale vždy pouze ten údaj, o kolik se liší předchozí údaj oproti aktuálnímu, plus znaménko. Komprese je to velmi efektivní, ale bohužel také dost složitá na pochopení a naprogramování.

Formát MIDI používá notový zápis. Vychází z toho, že každá karta obsahuje část, která podle zadaných not přehraje určitý nástroj. MID soubor tedy neobsahuje kompletní záznam zvuku, ale pouze informaci o tom, kterou notu, na kterém nástroji hrát jakou dobu, v jaké hlasitosti, a vyvážení (popř. s dalšími efekty). Možnosti jsou buď FM syntéza (málo kvalitní), GM (dobrá) nebo XG (výborná, téměř jako WAVE). Soubory MID jsou pro všechny stejné (resp. všechny tři syntézy dokáží přehrát libovolný soubor MID, ale pokud chcete využít např. všech efektů XG, musíte takový MID vytvořit - starší syntézy prostě nové příkazy budou jen ignorovat). Ideální řešení je napsat si vlastní editor, který bude vytvářet vlastní soubory přesně tak, jak je budete chtít (tj. ukládat jen vždy notu, délku, nástroj, prostě rovnou příkazy, které budete posílat do zvukové karty).

Soubory modulů MOD, atd. využívají to nejlepší z WAVů a MIDI. Soubor vlastně obsahuje banků souborů WAV většinou v kvalitě mono a různé frekvenci, a pak seznam not, které se mají hrát. Prakticky je zde až 8 kanálů, takže může hrát až 8 zvuků současně. Je zde hlavní seznam, který obsahuje ukazatele na tabulky s noty v kanálech, takže můžete napsat refrén a pak ho opakovat pouhým zopakováním ukazatele na něj. V každé notě je informace nejen o tom, který zvuk se má zrovna přehrát, ale také jaké efekty se na něj mají uplatnit. Výsledek je jasný: zvuky (nástroje) jsou uloženy jen jednou, mají vyšší kvalitu než zvuky v MIDI, a přitom se volají pomocí úsporných not, takže i hodinu dlouhý MOD bude mít třeba jen 1 MB. Opět se zde nabízí řešení napsat si vlastní formát, kdy uložíte soubory WAV a pak vytvoříte tabulku, která je bude v určitých časech volat a zvuková karta je namixuje jako každý jiný zvuk. MOD je oproti MP3 méně kvalitní, ale vyžaduje méně času CPU na dekódování a navíc umí např. dočasně zapnout/vypnout některé své stopy (viz. např. NFS3, kdy se při rychlejší jízdě přidávají bubny).

Doporučuji na tyto věci použít cizí jednotky. Např. RAIN, který využívá MIDAS, dokáže přehrávat zvuky jak pod DOSem, tak pod Windows, takže Vaše DOSová aplikace bude hrát i pod Windows XP! RAIN dokáže přehrávat soubory MP3 (ano, i pod DOSem), MOD, S3M, XM (možná i IT) a WAV (bohužel, ačkoliv MIDAS údajně umí i ADPCM, RAIN to zatím nepodporuje a jeho vývoj je již zastaven, nicméně autor nemá nic proti tomu, abyste si ho přepsali podle svých představ). Má spoustu nastavení kvality a jeho využívání je opravdu jednoduché. Umožňuje přehrávat několik souborů současně, ovšem s tím, že se soubory musí vyskytovat na disku (nikoliv v paměti), což bohužel není zrovna nejšťastnější (ale MIDAS samotný takové omezení nemá, ovšem jeho vývoj je již také zastaven, navíc si ho pod patronát vzala komerční firma).

Popisy jednotlivých formátů se dají najít na Internetu, popř. i v programu ATHelp. Popis hlaviček není to, co by nás trápilo, neboť je to ve srozumitelné formě popsané snad všude. Horší je již ukládání samotných dat, neboť např. u MODů jsou sice popsány noty, ale už ne možnosti realizace efektů a způsob samotného hraní. Zdrojových kódů v C, Pascalu či ASM je také hromada, ovšem pochopit 90 kB textu není zrovna něco, čím by se někdo chtěl zabývat.


Práce se zvukem

Než začneme naše zvuková data posílat do zvukové karty (jejich načtení z disku provádějte pomocí BLOCKREAD do nějaké konvenčí paměti (lépe XMS), zápis na disk probíhá podobně), naučíme se pár věcí, která s nimi budeme provádět. Zde uvidíte, proč je důležité, aby zvuky měly frekvenci v násobku 11025, atd. Nejprve si ujasníme, jak vypadá ticho. U 16 bitového zvuku je to 0. U 8 bitového zvuku to je 128. Pokud nevíte proč, prostudujte si způsob uložení čísel se znaménky a bez nich. Na zvuk se budeme dívat jako na sekvenci samplů (na 1 vteřinu min. 11025), z nichž každý se skládá z 1 až 2 vzorků (mono/stereo), z nichž každý obsahuje 1 až 2 byty (8/16 bitů).

První probereme jednoduché efekty. Pokud chcete přehrávat zvuk obráceně (reverzně), šáhněte do svých znalostí o otáčení obrázků. Máte-li samply uložené stylem 012345, tak prostě prohoďte 0 a 5, 1 a 4, 2 a 3 (pokud máte lichý počet, tak se prostřední sampl nechá tam, kde je). Občas se používá tzv. inverzní vlna. Není to nic jiného, než že se každý vzorek (!) jednoduše převrátí. Tedy pokud máte BYTE, provedete:


Vzorek := not Vzorek;  

Není to sice moc přesné, protože data 127 (-1) se stanou 128 (0), obráceně, ale je to zanedbatelná chyba oproti rychlosti, kterou získáme ušetřením IF a INC/DEC. Pokud máte INTEGER, musíte provést toto:


Vzorek := -Vzorek;  

Tady se už žádné chyby nedopouštíme. Musíme ovšem pracovat s údajem jako s Integerem, nikoliv s Wordem. U Wordu by tato operace vypadala následovně:


if Vzorek <> 0 then
begin
 if Vzorek < 32768 then Inc(Vzorek,32767)
  else Vzorek := not Vzorek;
end;  

Opět tu máme menší chybičku u $ffff -> 0, ale ta tvoří jen 0.002%, takže je zanedbatelná. To byly ty jednodušší efekty. Nyní něco složitějšího. Máme-li zvuk v mono a chceme ho mít ve stereo, uděláme to velmi jednoduše. Prostě každý vzorek zduplikujeme, takže namísto vzorků L1 L2 L3 budeme mít nyní L1 L1 L2 L2 L3 L3. Pokud máme stereo a chceme mono, můžeme buď jeden kanál prostě zahodit a uložit jen jeden, nebo musíme oba kanály sloučit do jednoho. Ideálně se používá mixování 50:50, tj. nejprve se oba kanály 2x ztlumí a pak se sečtou (jistě víte z fyziky, tak se sčítají dvě sinusové vlny). Pracovat s neznaménkovým bytem, který vyjadřuje sinusovku není zrovna moc jednoduché. Operace budou vypadat pro 8 a 16 bitové číslo takto (nemůžeme používat SHR, neboť to nepočítá se znaménkem - ve své podstatě ani nemůže):


var L,R,Out : shortint;
    MonoB,PravyB,LevyB : byte;
    MonoI,PravyI,LevyI : integer;
begin
(* 8 bitový mix kanálů *)
 if LevyB < 128 then L := -(128-LevyB)
  else L := LevyB-128;
 if PravyB < 128 then R := -(128-PravyB)
  else R := PravyB-128;
 Out := (integer(L)+integer(R)) div 2;
 {Out := L div 2+R div 2;}
 if Out >= 0 then MonoB := Out+128
  else MonoB := 128-Out;
(* 16 bitový mix kanálů *)
 MonoI := LevyI div 2+PravyI div 2;
end;  

Zajímavý efekt je také psedo-stereo. To vezmete mono zvuk, a vytvoříte z něj stereo pouhým posunutím jednoho kanálu oproti tomu druhému. Jinými slovy, převedete zvuk na stereo takto:


L0 L1 L2 L3 L4 L5 L6 L7 L8 L9	(mono)


L0 L1 L2 L3 L4 L5 L6 L7 L8 L9
         L0 L1 L2 L3 L4 L5 L6 L7 L8 L9  

Délka posunutí je závislá na tom, jaké šířky efektu chcete dosáhnout. Když chceme měnit bitáž, tj. 8<->16, provedeme následující výpočty (jsou celkem jednoduché, ale vzhledem k nutnosti dělení a násobení se nedoporučuje toto provádět během real-time hry, ale spíše při načítání levelu, atd):


var Vzorek : shortint;
    VzorekB : byte;
    VzorekI : integer;
begin
(* 8 -> 16 bitů *)
 if VzorekB < 128 then Vzorek := -(128-VzorekB)
  else Vzorek := VzorekB-128;
 VzorekI := integer(Vzorek)*256;
(* 16 -> 8 bitů *)
 Vzorek := VzorekI div 256;
 if Vzorek >= 0 then VzorekB := Vzorek+128
  else VzorekB := 128-Vzorek;
end;  

Poslední, co ještě můžeme na zvuku změnit, je jeho frekvence. Protože existuje několik standardních, tak můžeme využít toho, že převod mezi 11 a 22 kHz používá násobič/dělič 2, stejně tak mezi 22 a 44 kHz. Mezi 11 a 44 to bude 4x. Změna na nižší frekvenci je jednoduchá: vypočteme si rozdíl STARA div NOVA a podle tohoto čísla vynecháme každý Xtý vzorek:


22 kHz -> 11 kHz	L1 R1 L2 R2 L3 R3 L4 R4
	výsledek:	L1 R1 L3 R3


44 kHz -> 11 kHz	L1 R1 L2 R2 L3 R3 L4 R4 L5 R5 L6 R6 L7 R7
			L1 R1 L5 R5  

Celkem logicky, pokud chceme převést frekvenci nižší na vyšší, budeme data přidávat (rozumějte tomu: převod zvuk standardně nijak nezrychluje, pouze mění jeho zpracování: k tomu, abyste změnili i rychlost zvuku musíte změnit jen počet jeho dat a pak ho buď přehrát na jiné frekvenci, nebo ho uložit do WAVu pod původní frekvencí - v tomto případě ale nemusíte měnit ani tak data jako spíše daný údaj v hlavičce WAVu!). Vycucat z prstu si je nemůžeme, takže je musíme zduplikovat. Tedy každý údaj zkopírujeme 2x až 4x podle toho, jaký nám vyšel násobič:


22 kHz -> 44 kHz	L1 R1 L2 R2
	výsledek:	L1 R1 L1 R1 L2 R2 L2 R2


11 kHz -> 44 kHz	L1 R1 L2 R2
			L1 R1 L1 R1 L1 R1 L1 R1 L2 R2 L2 R2...  

Ovšem mnohem kvalitnější je převod s dopočtem nových samplů. Tedy vzorky nebudeme jen tak kopírovat, ale vytvoříme "nové". Pro násobič 2x bude výpočet nového vzorku "B := (A+C) DIV 2". Pro násobič 4 budou vzorky B až D mezi původními vzorky A a E vypadat takto:


	C := (A+E) div 2;
	B := (A+C) div 2;
	D := (C+E) div 2;  

Takto by to platilo pochopitelně pro 16 bitové vzorky. Pro 8 bitové je musíme nejprve převést na nějaký znaménkový typ. Samozřejmě, lze počítat i s číslem uloženým jako dvojkový doplněk a později si to ukážeme, ale zatím si tím nebudeme komplikovat život. Pokud chcete zvuk pustit 2x rychleji, nemusíte ho vždy nutně převádět (tzv. převzorkovávat). Např. pokud Vaše zvuková karta přehrává zvuky na frekvenci 44 kHz a Vy máte zvuk na frekvenci 22 kHz, klidně ho pošlete do ní. Zvuk se přehraje 2x tak rychle. Pokud ho ovšem máte na 11 kHz, musíte ho nejprve na 22 kHz převést. Pokud máte zvuk na 44 kHz, tak takéž na 22 kHz. Pokud chcete zvuk naopak zpomalit, musí mít větší frekvenci než samotná karta (např. pokud karta jede na 44 kHz, Váš zvuk bude mít 88 kHz).

Dalším efektem je změna hlasitosti. Hlasitost se mění tak, že u každého vzorku v samplu (nebo jen u vybraného kanálu) prostě změníme hodnotu údaje. Pro Integer platí, že


VZOREKn := (VZOREKs*NOVA) div STARA  

Samozřejmě to zase vyžaduje čísla typu Integer, nebo zde raději lépe Longint (kvůli přetečení). Když známe hlasitost, můžeme vytvořit např. efekt fade. To se dělí na "in" nebo na "out", podle toho, zda má zvuk postupně nabíhat, nebo se má ztlumovat. Není v tom nic jiného, než že určíte počet kroků (samplů), a pro každý sampl nastavíte hlasitost tímto stylem


VZOREKn := (VZOREKs*NOVA*AKTKROK) div (STARA*POCETKROKU)  

Pokud chcete Fade zjednodušit na efekt, kdy je jedna z hlasitostí 100% a druhá 0%, zjednoduší se vzoreček na tento:


VZOREKn := (VZOREKs*AKTKROK) div POCETKROKU

Opět je nutné mít čísla v rozsahu -/+, a ne jako Byte bez znaménka (vyšly by Vám nesmysly). Přehrávat jeden zvuk na zvukové kartě většinou nestačí. Je pravda, že standardně zvuková karta přehrává pouze 1 souvislý zdroj dat, ale kolik je v něm zvuků, to už jí nezajímá. Jak se dá přimixovat zvuk? Jednoduše, prostě vzorky sečtete:


NovyL := PrvniL + DruhyL;
NovyR := PrvniR + DruhyR;  

Kde PrvniX může být také původní NovyX. To platí pro Integery. Jak jsem se zmiňoval kdysi u MMX, zvuky je vhodné před sečtením ztlumit tolikrát, kolik zvuků maximálně budete chtít mixovat (ty ostatní prostě zahodíte, viz. Doom), nebo je ztlumíte jen 2x a pak si pohlídáte, aby Vám výsledek nepřetekl přes mez (budete ho muset oříznout, tzv. Clip). Pokud chcete sčítat 8 bitové údaje bez znaménka a zároveň je i zmenšit, můžete využít svých velkých znalostí a použít malý trik. Abyste mohli i tato čísla přičítat normálně pomocí + do bufferu (zvuk se začne přehrávat tehdy, když ho namixujete - jakmile mix dokončíte, můžete začít mixovat znovu, nebo data, ze kterých jste četli, uvolnit a nahradit jinými, počítač je už využívat nebude - pokud je nebudete potřebovat Vy), musíte si je nejprve upravit. Upozorňuji, že tato úprava není vhodná pro nic jiného než pro mixování nebo pro metody, které nepotřebují měnit obsah vzorků (změna frekvence směrem dolů, atd.). Mějme příklad, kdy chceme mixovat současně až 4 zvuky uložené jako 8 bitové WAVy. Pro každý vzorek každého zvuku provedeme před namixováním tuto operaci:


NOVY := STARY shr 2 - 32  

Jaký to má význam? Uvědomte si, tak je zvuk uložen. 0 je reprezentována jako 128 (což je zároveň standardní hodnota bufferu, do kterého budeme mixovat). Touto operací z ní uděláme skutečně 0. Z kladných čísel 129-255 se nám stala čísla 1-31, a se "záporných" čísel 127-0 se nám stala čísla -1 až -31, uložené do bytu jako 255 až 206. Tento systém se spoléhá na to, že nezáleží na tom, kde je umístěná 0, resp. středová poloha membrány. Pokud budete vibrovat mebránou mezi úrovněmi -16 až +16, mělo by to být stejné, jako vibrování mezi úrovněmi +32 až +64. Takto je tedy možné sčítat dohromady 8 bitové zvuky bez rizika přetečení (samotné SHR 2 nestačí). Pokud jste to ale moc nepochopili (jako já), nic se nestane, pokud budete zvuky mixovat se znaménkem a pak je jednoduše převádět. Ono totiž provádění různých efektů se vyplatí na 16 bitových číslech, neboť dosáhnete lepší přenosti. Pokud Vám ale jde pouze o sčítání zvuků, můžete tuto metodu použít.

Podobně odečítáním můžete např. ze zašumněného zvuku jednoduše odečíst záznam šumu a pokud se trefíte na stejnou fázi, šum zmizí a zůstane jen samotný zvuk (podobně se dá odečítat i zpěv z písničky, atd.). Když zkloubíte všechny znalosti dohromady, můžete si vytvořit i jednoduchou ozvěnu (echo). Ta se provádí tak, že se vezme zvuk, trochu se zlumí, a namixuje se sám do sebe s tím, že se posune o pár vteřin dozadu (nebo jen pár zlomků vteřiny, čímž se vytváří také zajímavá ozvěna). Na každý tento nový zvuk můžete ještě pustit mírnější fade off než ho přimixujete, nebo na jeho konec dát trochu fade in, čímž ho jakoby zvýrazníte. Expermientům jsou dveře otevřeny, takže si můžete vytvořit svou vlastní databanku různých ozvěn.

Zvuky se doporučuje mít uložené v XMS paměti, aby nebylo nutné je neustále načítat z disku. Když budete chtít zvuk přehrát, přenesete si ho do konvenční, namixujete do bufferu karty a ona si ho už sama přehraje. Na 99% se setkáte s problémem, kdy je buffer karty omezen na 65520 bytů (většinou se ovšem dává jen 32 kB a dělí se na 2-4 části kvůli omezení "praskání") a Vy potřebujete přehrávat větší zvuky. Není nic snažšího. U každého zvuku si vytvořte údaj o tom, jak je velký a jakou část jste aktuálně přehráli. Když dáte jeho mix, namixujte 32 kB část (pokud je zvuk větší) a zvyšte ukazatel u toto velikost. Jakmile zvuková karta přehraje 32 kB dat, namixujete dalších 32 kB od dané pozice a zase tuto pozici zvyšte (nyní na 64 kB). V praxi se ale mixuje právě jen tolik dat, kolik se vejde do již přehrané části (8 až 16 kB), takže budete ukazatel zvyšovat o tuto velikost. Pokud chcete zvuk přehrávat současně několikrát (např. Vám zrovna umírají ve hře dvě příšery), nemusíte ho mít uložený několikrát. Stačí, když budete mít pouze několik ukazatelů aktuálních pozic.


V příštím díle se podíváme na praktickou realizaci, tedy jak rozběhnout zvukovou kartu. Naučíme se nejen přehrávat zvuky (a tedy i případně i MODy), ale také MIDI (FM a GM), a trochu nakousneme i nahrávání ze zvukové karty do paměti (nebo na disk).


POKRAČOVÁNÍ PŘÍŠTĚ ...

2006-12-06 | Martin Lux
Reklamy:
„Bůh stvořil člověka, ale nedal si to patentovat, a tak to teď po něm může dělat kdejakej blbec.“ Jan Werich