Allegro - MP3 potřetí (19. díl) - Builder.cz - Informacni server o programovani

Odběr fotomagazínu

Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!

 

Zadejte Vaši e-mailovou adresu:

Kamarád fotí rád?

Přihlas ho k odběru fotomagazínu!

 

Zadejte e-mailovou adresu kamaráda:



C/C++

Allegro - MP3 potřetí (19. díl)

allegro

10. února 2003, 00.00 | Představíme si nový datový typ a napíšeme si vlastní ukázkový program. Naučíme se, jak pomocí AllegraMP3 nechat přehrávat hudbu automaticky na pozadí a nějaké další užitečné funkce.

{AllegroMP3} Poslední dva díly jsme se, stručně řečeno, zabývali příkladem a instalováním knihovny AllegroMP3. Dnešní díl si ukážeme něco nového, co nám může zpříjemnit cestu při programování her. Např. přehrávání hudby na pozadí a také přehrávání stále dokola, bez našeho zásahu.

Rozdíl mezi ALMP3_MP3STREAM a ALMP3_MP3

O datové struktuře ALMP3_MP3STREAM a o tom jak funguje jsme si už něco řekli již v minulých dílech. V dnešním díle budeme podrobněji mluvit o struktuře ALMP3_MP3. Ale abych vysvětlil lépe rozdíly, tak malinko připomenu první strukturu.

ALMP3_MP3STREAM

Jak z názvu vypovídá jedná se o STREAMING, neboli datové proudy (či proud). Přehrávání probíhá tak, že se do paměti načte kus souboru a ten se začne přehrávat. Později např. v herní smyčce se neustále tento datový proud aktualizuje, nebo spíše se načítá z disku další část souboru, která nahradí tu dosavadní. To znamená, že musíme v programu stále volat "doplňování" našeho souboru v paměti a také dekódování souboru. Výhoda je taková, že tato metoda spotřebuje jen malou část paměti. Počítám tam 100 kb. Podle toho jak velký buffer použijeme.

ALMP3_MP3

Rozdíl tohoto datového typu oproti minulému je ten, že tato struktura načte do paměti CELÝ soubor, který se může přehrávat jak chce. Celková práce s tímto typem je jednodušší co do kódování hry (programu) a můžeme s ní dělat přímo psí kusy :) jelikož máte celý soubor v paměti. Nevýhoda je opak výhody STREAMINGu. Tedy, že zabere větší kus paměti. Pokud tedy vezmeme MP3Trojku, která je dlouhá asi 3 minuty v kvalitě 128 kb/s tak to znamená pro nás asi tak 2-3 MB paměti. Hodnotu můžeme zmenšit tím, že použijeme horší kvalitu nebo dokonce mono místo sterea, ale zas tak moc bych to nepřeháněl to šetření. Záleží na volbě každého z Vás. Pokud ale budete mít v programu jednu, dvě písničky a hru postavíte na 32 MB, tak se zas tak nic neděje.

Dekódování

To bylo porovnání a představení nového datového typu ALMP3_MP3. Další co stojí za zmínku je přehrávání. Načtený soubor v paměti se potřebuje ještě dekódovat, což se jedná o nárůst původního souboru až na několik násobek. Tedy musíme ještě uvolnit (resp. my jenom řekneme kolik a AllegroMP3 to uvolní za nás) kus paměti pro dekódování. Většinou je to násobek dvěma, což může mít v ideálním případě 32 nebo 64 kB. Více nám prozradí následující příklad, který uvádím v celém znění.

Příklad na ALMP3_MP3

#include <string.h>
#include <stdio.h>
#include <allegro.h>
#include "almp3.h"

void putstr(char *s); // prototyp

#define BUFSZ   (1>>16) /* Velikost bufferu pro dekodovaní */


ALMP3_MP3 *mymp3; // nase hudba - pro jednoduchost globalni promenna


ALMP3_MP3 *open_mp3_file_full(char *filename) {
  FILE *f = NULL;
  ALMP3_MP3 *m = NULL;
  void *data;
  int len;
  int error=0;
  char Integer[21];

  if (!(data = (void *)malloc(sizeof(char)*10000000))) {
	error = 1;
    goto error;
  }

  if ((f = fopen(filename, "rb"))== NULL) {
	error = 2;
    goto error;
  }

  if ((len = fread(data, 1, 10000000, f)) <= 0) {
	error = 3;
    goto error;
  }

  if (!(m = almp3_create_mp3(data, len))) {
	error = 4;
    goto error;
  }

  // pro jistotu si vypiseme velikost 
  // souboru kterou jsme nacetli
  memset(Integer,0,21);
  itoa(len,Integer,10);
  putstr(Integer);

  fclose(f);
  free(f);
  return m;

  error: // zde se program dostane jen pri chybe
  putstr("CHYBA");
  
  switch (error) {
	case 1:putstr("CHYBA: Málo paměti pro malloc");break;
	case 2:putstr("CHYBA: Otevření souboru");break;
	case 3:putstr("CHYBA: Načtení dat ze souboru");break;
	case 4:putstr("CHYBA: ");break;

  }
    
  fclose(f);
  free(m);
  free(f);
  return NULL;
}


int main() { 
  char *s="_a.mp3";

  allegro_init();

  install_timer();
  install_keyboard();

  if (set_gfx_mode(GFX_SAFE, 640, 480, 0, 0) < 0) {
    allegro_message("Error setting video mode.\n");
    return 1;
  }
  clear_to_color(screen, makecol(255, 255, 255));

  /* nastavime volume v Allegru na max. */
  set_volume_per_voice(0);

  if (install_sound(DIGI_AUTODETECT, MIDI_NONE, 0) < 0) {
    set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
    allegro_message("Error installing sound.\n");
    return 1;
  }

// hlavni cast kodu, ktera prehrava

  putstr(s); // tiskne jmeno souboru.


  if (mymp3 = open_mp3_file_full(s)) {
    if (almp3_play_ex_mp3(mymp3, BUFSZ, 255, 128,1000,1) != ALMP3_OK)
		putstr("error play");
  }
  else 
    putstr("Error opening.");

  // zde muze byt smycka programu...  
  while (!keypressed()) {
  	  almp3_poll_mp3(mymp3);
  }


  almp3_destroy_mp3(mymp3);

  free(mymp3);

// konec hlavni casti kodu, ktery prehrava

  allegro_exit();

  return 0;
}
END_OF_MAIN();


/* jednoducha funkce pro vystup */
void putstr(char *s) {
  static int y = 0;
  text_mode(-1);
  textout(screen, font, s, 0, y, makecol(0, 0, 0));
  y += text_height(font);
}
[-more-]{Popis ukázkového příkladu}

Popis ukázkového příkladu

Vezmeme to hezky popořadě a od začátku (samozřejmě, že to co už známe nebudeme komentovat). Jako první náš může zabrzdit tento řádek

ALMP3_MP3 *mymp3;

Jedná se o proměnnou, ve které budeme uchovávat načtený celý soubor. Oproti minulé struktuře, kde jsme museli uchovávat mj. i pointer na soubor, zato tady jej máme rovnou celý. Dále následuje funkce

ALMP3_MP3 *open_mp3_file_full(char *filename)

která je malinko upravená z minulého příkladu. Jako parametr dostane jméno souboru a vrací pointer na strukturu ALMP3_MP3. Není zde skoro nic neznámého a proto uvedu jenom to co by nás mohlo překvapit. A to je tento řádek

if (!(m = almp3_create_mp3(data, len))) {

Tato funkce bere jako parametr pointer na data a délku dat. Obojí jsme získali pomocí pár řádku nad. Opět vrací pointer na ALMP3_MP3 a pokud nenastala chyba, vracíme tento pointer na nově alokovanou paměť obsazenou naším souborem s hudbou pomocí return. Zbytek jsou jen chybová hlášení apod. Tedy všechno co je známé z jazyka C.

Nyní se přesuneme na nejdůležitější část programu, a to až do funkce main. Ostatní jako je inicializace zůstává stejná. Hlavní část kódu vypadá takto

  if (mymp3 = open_mp3_file_full(s)) {
    if (almp3_play_ex_mp3(mymp3, BUFSZ, 255, 128,1000,1) != ALMP3_OK)
		putstr("error play");
  }
  else 
    putstr("Error opening.");

  // zde muze byt smycka programu...  
  while (!keypressed()) {
  	  almp3_poll_mp3(mymp3);
  }

Jako první otestujeme jestli se podaří soubor otevřít. Jeho jméno máme uschované v proměnné s. Pokud se budete program pokoušet překládat, doplňte si tam, prosím, své jméno. Pokud otevření proběhne vše v pořádku zkusíme spustit písničku pomocí této funkce

int almp3_play_ex_mp3(ALMP3_MP3 *mp3, int buffer_len, int vol, int pan, int speed, int loop);

Jako první parametr předáváme soubor (neboli pointer na strukturu ALMP3_MP3), další tři jsou stejné jako ve funkci almp3_play_mp3stream popsané v minulém díle. Pro úplnost, velikost bufferu je ta, která se použije pro dekódování písničky v paměti. Poslední dva parametry stojí za zmínku. speed znamená rychlost přehrávání. Hodnota 1000 znamená normální rychlost, 500 poloviční a 2000 dvakrát rychlejší.
Poslední parametr je tzv. vlajka (flag). Pokud je hodnota 0, znamená to, že se písnička poté co dojede nakonec, zastaví a přehrávání dál nepokračuje. Pokud je hodnota 1 znamená to, že se písnička bude přehrávat stále dokola. To můžete použít například pro hudbu na pozadí.

Pokud nastane nějaká chyba při volání funkce, dáme to opět najevo pomocí výpisu. Když všechno proběhne v pořádku dostaneme se až k hlavní smyčce programu. Zde opět opakovaně voláme funkci almp3_poll_mp3, která dekóduje hudbu v paměti o velikosti našeho bufferu zadaného při přehrávání.

Rozdíl od minulé verze pomocí STREAMINGu je ten, že nyní máme celý soubor v paměti a nemusíme ho již dále načítat. Ale opět musíme volat funkci, která nám dekóduje a aktualizuje buffer s hudbou. To se dá ale také lehce obejít. Dokonce je na to v AllegruMP3 funkce, která to udělá za nás za minimální práce.

Přehrávání opakovaně dokola

Jak to udělat, abych nemusel volat stále dokola funkci almp3_poll_mp3? Zkuste nahradit minulý výřez z programu tímto:

  if (mymp3 = open_mp3_file_full(s)) {
    if (almp3_play_ex_mp3(mymp3, BUFSZ, 255, 128,1000,1) != ALMP3_OK)
        putstr("error play");
    else {
       almp3_start_autopoll_mp3(mymp3, 20);
    }
  }
  else 
    putstr("Error opening.");

  // zde muze byt smycka programu...  
  while (!keypressed()) {
		// vlastni program
  }

Otevření a přehrání souboru je stejné. Hlavní rozdíl je v tom, že už se nemusí v hlavní smyčce programu volat funkce almp3_poll_mp3. A to všechno nám způsobila tato funkce

almp3_start_autopoll_mp3(mymp3, 20);

kterou jsme zavolali před vstupem do hlavní smyčky. To znamená, že se nyní bude naše hudba přehrávat pořád dokola a to bez našeho zásahu a volání nějaké další funkce.

Prototyp funkce je následující

void almp3_start_autopoll_mp3(ALMP3_MP3 *mp3, int speed);

První parametr je jasný, a druhý je docela důležitý. Říkáme tím programu, po jak dlouhé době (v milisekundách) chceme, aby za nás volal na pozadí funkci almp3_poll_mp3. Pro hru, která má kolem 50 FPS jsme zvolili hodnotu 20 ms, což je dostačující. Pokud by byla Vaše hudba trhaná, dejte hodnotu menší, která ba vám měla problém bezesporu vyřešit.

Pokud chcete automatické dekódování bufferu a jeho aktualizaci ukončit můžete to provést pomocí funkce

void almp3_stop_autopoll_mp3(ALMP3_MP3 *mp3);

Uvolnění se děje pomocí funkce

void almp3_destroy_mp3(ALMP3_MP3 *mp3);

Jako parametr standardně pointer na strukturu ALMP3_MP3.

Závěr

Na závěr ještě dvě užitečné funkce.

První funkce, která zastaví přehrávání hudby je tato

void almp3_stop_mp3(ALMP3_MP3 *mp3);

a druhá, která přesune aktuální pozici přehrávání na začátek je

void almp3_rewind_mp3(ALMP3_MP3 *mp3);

Obe dvě funkce berou jako parametr pointer na strukturu ALMP3_MP3.

Knihovna AllegroMP3 je velice rozsáhlá a její použitelnost je široká co se týče přehrávání hudby. Pokud tedy potřebujete nějaké funkce, které vám vracejí informace nebo nějaké parametry o vašem souboru či něco podobného, nahlédněte, prosím, do dokumentace k AllegruMP3.

Přeji Vám hodně štěstí při programování nejen her s AllegremMP3.

Zdrojový soubor (pro obě verze) si můžete stáhnout zde.

Obsah seriálu (více o seriálu):

Tématické zařazení:

 » Rubriky  » C/C++  

 

 

 

Nejčtenější články
Nejlépe hodnocené články

 

Přihlášení k mému účtu

Uživatelské jméno:

Heslo: