Hlavní navigace

SDL: Hry nejen pro Linux (19)

Michal Turek 7. 7. 2005

Vše, co se týká SDL audio funkcí, už máme probráno, takže se zkusíme podívat na rozšiřující knihovnu SDL_mixer. Knihovna SDL_mixer poskytuje snadno použitelné funkce pro mixování zvuků a hudby. Je vhodná obzvlášť pro ty, kterým připadá standardní SDL audio API příliš nízkoúrovňové a strohé.

SDL_mixer

Knihovna SDL_mixer poskytuje snadno použitelné funkce pro mixování zvuků a hudby. Je vhodná obzvlášť pro ty, kterým připadá standardní SDL audio API příliš nízkoúrovňové a strohé. Aby bylo se SDL_mixerem vše co nejjednodušší, přímo v knihovně lze nalézt podporu i pro nahrávání zvuků z formátů, jako jsou .WAV, .AIFF, .VOC, .OGG, .MP3 a další, u některých ale jen s použitím externích dekodérů.

SDL_mixer je, stejně jako SDL, šířen pod licencí GNU LGPL. Veškeré rozhraní je deklarováno v hlavičkovém souboru SDL_mixer.h a při linkování programu je nutné přidat do příkazové řádky řetězec -lSDL_mixer. Všechny funkce z této knihovny začínají na předponu ‚Mix_‘.

Při zakládání aplikace byste si měli vždy rozmyslet, zda budete pro zvuky a hudbu používat SDL_mixer, nebo SDL audio funkce. Kombinace obou technik je sice možná, ale nemusí být zrovna šťastným nápadem. U SDL_mixeru byste se měli rozhodně vyvarovat volání funkcí jako SDL_OpenAudio(), SDL_CloseAudio(), SDL_PauseAudio(), SDL_LockAudio(), SDL_UnlockAudio() apod., mohou být konfliktní s jejich Mix_*() analogiemi.

Obecné funkce

Inicializace knihovny a současně i otevření audio zařízení se v SDL_mixeru provádí funkcí Mix_OpenAudio().

int Mix_OpenAudio(int frequency, Uint16 format,
        int channels, int chunksize); 

Parametry by měly být jasné. Místo konkrétní frekvence může být použita symbolická konstanta MIX_DEFAULT_FRE­QUENCY, která má hodnotu 22050 Hz. Za druhý parametr, formát vzorků, je možné předat libovolnou z konstant definovaných v SDL, popř. MIX_DEFAULT_FORMAT má hodnotu AUDIO_S16SYS. U třetího parametru označuje jednička mono a dvojka stereo, chunksize definuje velikost každého mixovaného bloku.

Funkce oznamuje chybu vrácením –1, je-li vše v pořádku, vrátí nulu.

Zavření zařízení a deinicializace knihovny jsou uskutečňovány funkcí Mix_CloseAudio(). Mix_GetError() slouží pro získání řetězce obsahujícího popis poslední chyby a pomocí Mix_SetError() ji lze definovat.

void Mix_CloseAudio();

char *Mix_GetError();
void Mix_SetError(const char *fmt, ...); 

V následujícím příkladu je otevřeno audio zařízení s předdefinovanou frekvencí a formátem, bude se jednat o stereo a velikost bloků dat bude 1024 bytů.

// Inicializace
if(Mix_OpenAudio(MIX_DEFAULT_FREQUENCY,
        MIX_DEFAULT_FORMAT, 2, 1024) == -1)
{
    printf("Mix_OpenAudio(): %s\n", Mix_GetError());
    return false;
}

// Deinicializace
Mix_CloseAudio(); 

Parametry aktuálně otevřeného audio zařízení lze získat voláním funkce Mix_QuerySpec(), která při chybě vrací nulu.

int Mix_QuerySpec(int *frequency, Uint16 *format, int *channels); 

Zvuky

Zvuky jsou v SDL_mixeru reprezentovány strukturou Mix_Chunk, jejíž popis není pro programování důležitý. Mělo by stačit předávat do funkcí ukazatele na její objekty.

Pro základní nahrávání zvuků ze souboru slouží funkce Mix_LoadWAV(). Předává se jí jméno souboru na disku a v případě úspěchu je vrácen ukazatel na zvuk, chyba je oznámena klasicky pomocí NULL. Druhá funkce, Mix_LoadWAV_RW(), se používá pro nahrávání ze SDL_RWops. Nenulová hodnota ve druhém parametru způsobí automatické zavření a uvolnění zdroje, když už není potřeba.

Mix_Chunk *Mix_LoadWAV(char *file);
Mix_Chunk *Mix_LoadWAV_RW(SDL_RWops *src, int freesrc); 

Další možností, jak nahrávat zvuky do aplikace, jsou dvě funkce Mix_QuickLoad_*(), které umožňují pracovat s daty v paměti. Už v době volání funkce musejí být zvuky ve výstupním formátu a v podstatě většina chyb není testována, použití může být tudíž relativně nebezpečné. Vždy byste měli vědět, co děláte.

Mix_Chunk *Mix_QuickLoad_WAV(Uint8 *mem);
Mix_Chunk *Mix_QuickLoad_RAW(Uint8 *mem); 

Po skončení práce s daným zvukem by se měl vždy pomocí Mix_FreeChunk() uvolnit.

void Mix_FreeChunk(Mix_Chunk *chunk); 

Hlasitost zvuku se dá softwarově nastavit voláním funkce Mix_VolumeChunk(), které se předává požadovaná hlasitost v rozsahu od nuly do MIX_MAX_VOLUME (=128). Návratovou hodnotou je předchozí hlasitost.

int Mix_VolumeChunk(Mix_Chunk *chunk, int volume); 

Jak poznáme dále, je tato funkce pouze jednou z možností, jak nastavit výslednou hlasitost zvukového výstupu.

Kanály a přehrávání

SDL_mixer defaultně alokuje celkem osm kanálů, v každém z nich může být v jednom okamžiku přehráván právě jeden zvuk. Pokud je spuštěn zvuk v kanálu, ve kterém se už něco přehrává, původní se zastaví a je spuštěn nový. Počet kanálů se dá upravit funkcí Mix_AllocateChan­nels().

int Mix_AllocateChannels(int numchans); 

Pokud bude požadovaný počet kanálů menší než původní, budou nejvyšší zavřeny a uvolněny. Návratovou hodnotou je počet nově alokovaných kanálů.

Podobně, jako šlo nastavit hlasitost zvuku, lze navíc nastavit i hlasitost kanálu. Za první parametr se předává pořadové číslo kanálu, v případě zadání –1 se operace provede nad všemi (platí obecně). Druhým parametrem se definuje požadovaná hlasitost.

int Mix_Volume(int channel, int volume); 

Návratovou hodnotou je aktuální hlasitost kanálu, popř. průměr, pokud byly zvoleny všechny.

Příkaz na přehrávání zvuku poskytuje funkce Mix_PlayChannel(). Prvním parametrem se opět volí kanál, –1 zde má význam prvního volného kanálu. Druhý parametr specifikuje přehrávaný zvuk a třetí počet opakování + 1 (nula jedenkrát, jedna dvakrát atd.). Speciální hodnotou je –1, označuje nekonečnou smyčku.

int Mix_PlayChannel(int channel, Mix_Chunk *chunk, int loops);

int Mix_PlayChannelTimed(int channel, Mix_Chunk *chunk,
        int loops, int ticks); 

U druhé uvedené funkce je možné v posledním parametru zadat navíc časový limit v milisekundách. Pokud po uplynutí této doby zvuk stále hraje, bude automaticky ukončen.

Obě funkce vracejí číslo kanálu, ve kterém bude zvuk přehráván, nebo –1 na znamení chyby. Většinou se jedná o to, že žádný kanál nebyl volný, ale může se také jednat o kritickou chybu.

Další možností, jak spustit přehrávání zvuku, je funkce Mix_FadeInChan­nel(). Jako poslední parametr se předává časový interval v milisekundách, během kterého zvuk postupně nabývá na síle.

int Mix_FadeInChannel(int channel, Mix_Chunk *chunk,
        int loops, int ms);
int Mix_FadeInChannelTimed(int channel, Mix_Chunk *chunk,
        int loops, int ms, int ticks); 

Zvuk přehrávaný v kanálu se dá pozastavit voláním funkce Mix_Pause() a následně obnovit pomocí Mix_Resume(). Pro kompletní stopnutí slouží jedna ze tří následujících funkcí. Mix_HaltChannel() zastaví přehrávání ihned, Mix_ExpireChannel() až po uplynutí časového intervalu a Mix_FadeOutChan­nel() způsobí postupné odeznívání.

void Mix_Pause(int channel);
void Mix_Resume(int channel);

int Mix_HaltChannel(int channel);
int Mix_ExpireChannel(int channel, int ticks);
int Mix_FadeOutChannel(int channel, int ms); 

Možná je to zbytečné připomínat, ale zvláště u těchto funkcí se lze velice často setkat s parametrem –1, který operuje nad všemi kanály.

Pomocí Mix_ChannelFi­nished() lze předat SDL_mixeru ukazatel na funkci, která se pak automaticky spustí, kdykoli se přehrávání v jakémkoli kanálu ukončí. Nikdy by se v ní neměly volat žádné audio funkce!

void Mix_ChannelFinished(void (*channel_finished)(int channel)); 

V následujícím příkladu se po ukončení přehrávání vypíše informační zpráva.

// Callback funkce
void ChannelFinishedCallback(int channel)
{
    printf("Kanál %d ukončil přehrávání.\n", channel);
}

// Předání ukazatele na funkci
Mix_ChannelFinished(ChannelFinishedCallback); 

Následující skupina funkcí slouží pro dotazy na stav přehrávání, nemělo by být třeba je zdlouhavě popisovat. Pokud je za kanál předáno číslo –1, vrací první dvě funkce počet kanálů, které vyhověly dotazům. Poslední uvedená funkce vrátí při dotazu jednu z konstant MIX_FADING_IN, MIX_FADING_OUT nebo MIX_NO_FADING. Parametr –1 zde není validní.

int Mix_Playing(int channel);
int Mix_Paused(int channel);
Mix_Fading Mix_FadingChannel(int which); 

Poslední funkce tohoto článku, Mix_GetChunk(), vrací ukazatel na zvuk, který je přehráván v definovaném kanálu, popř. byl přehráván jako poslední. Jelikož už může být zvuk uvolněn, nemusí být ukazatel v dané chvíli validní!

Mix_Chunk *Mix_GetChunk(int channel); 

Ukázkové programy

SDL_mixer

Aplikace inicializuje SDL_mixer, otevře audio zařízení a nahraje zvuk. Začátek přehrávání je umožněn stiskem mezerníku a konec pomocí enteru. V obou případech je ponechána doba tří sekund na postupné nabírání na síle resp. odeznění. (Zdrojový kód se zvýrazněním syntaxe.)

Download

Pokračování

Ze SDL_mixeru máme probránu cca polovinu, takže se budeme příště věnovat té druhé. Bude především o hudbě a efektech.

Našli jste v článku chybu?

4. 11. 2009 20:36

Tommy (CZ) (neregistrovaný)

Potřeboval bych poradit ohledně přidávání zvuků do volného kanálu. Když zavolám funkci Mix_PlayChannel() s parametrem –1 pro kanál, mělo by to najít volný kanál a v něm spustit přehrávání. Jenže když se volný kanál nenajde, tak se nový zvuk prostě nepřehraje. No a já bych potřeboval podobnou funkci, která by v případě nenalezení volného kanálu přerušila přehrávání nejdéle běžícího zvuku v jiném kanálu a místo něj přehrála ten nový. Chci se jen zeptat zda nějaká taková funkce už existuje v SDL, n…

21. 7. 2007 11:44

nikdo (neregistrovaný)
Ten wav je nějak komprimovaný. Jestli je v nějakém (MP3) kodeku, tak tam zkus dát příslušné dll, i když nevím, jestli to pomůže.
Vitalia.cz: Říká amoleta - a myslí palačinka

Říká amoleta - a myslí palačinka

Lupa.cz: Slevové šílenství je tu. Kde nakoupit na Black Friday?

Slevové šílenství je tu. Kde nakoupit na Black Friday?

Podnikatel.cz: Vládu obejde, kvůli EET rovnou do sněmovny

Vládu obejde, kvůli EET rovnou do sněmovny

DigiZone.cz: Česká televize mění schéma ČT :D

Česká televize mění schéma ČT :D

Podnikatel.cz: Přehledná titulka, průvodci, responzivita

Přehledná titulka, průvodci, responzivita

Podnikatel.cz: EET zvládneme, budou horší zákony

EET zvládneme, budou horší zákony

Podnikatel.cz: Víme první výsledky doby odezvy #EET

Víme první výsledky doby odezvy #EET

Podnikatel.cz: 1. den EET? Problémy s pokladnami

1. den EET? Problémy s pokladnami

Měšec.cz: Finančním poradcům hrozí vracení provizí

Finančním poradcům hrozí vracení provizí

Vitalia.cz: To není kašel! Správná diagnóza zachrání život

To není kašel! Správná diagnóza zachrání život

DigiZone.cz: ČT má dalšího zástupce v EBU

ČT má dalšího zástupce v EBU

Vitalia.cz: Chtějí si léčit kvasinky. Lék je jen v Německu

Chtějí si léčit kvasinky. Lék je jen v Německu

Vitalia.cz: Jsou čajové sáčky toxické?

Jsou čajové sáčky toxické?

Měšec.cz: Kdy vám stát dá na stěhování 50 000 Kč?

Kdy vám stát dá na stěhování 50 000 Kč?

Lupa.cz: Babiš: E-shopů se EET možná nebude týkat

Babiš: E-shopů se EET možná nebude týkat

DigiZone.cz: NG natáčí v Praze seriál o Einsteinovi

NG natáčí v Praze seriál o Einsteinovi

120na80.cz: Jak oddálit Alzheimera?

Jak oddálit Alzheimera?

Lupa.cz: Avast po spojení s AVG propustí 700 lidí

Avast po spojení s AVG propustí 700 lidí

DigiZone.cz: Sony KD-55XD8005 s Android 6.0

Sony KD-55XD8005 s Android 6.0

Lupa.cz: Proč firmy málo chrání data? Chovají se logicky

Proč firmy málo chrání data? Chovají se logicky