http://nothings.org/stb_vorbis
Kukaan käyttänyt kyseistä "kirjastoa"? Kuinka sen avulla voi toistaa ogg-tiedostoja? Käytän Windowsia ja Dev-C++.
Ilmeisesti stb_vorbis_decode_filename-funktiolla voi helposti dekoodata ogg-tiedoston muistiin, mutta mihin muotoon se dekoodaa ja millä sen voisi toistaa? Kenties winmm:llä jotenkin? Olen todella aloittelija näissä, joten voisiko joku tehdä ihan simppelin esimerkin.
Kirjastoa ennestään tuntemattomana väittäisin, että tällä pääset alkuun:
struct aani { int kanavia; int sampleja_sekunnissa; int sampleja; short *data; }; struct aani lataa_aani(const char *tiedosto) { struct aani ret; stb_vorbis *f; stb_vorbis_info info; /* Haetaan info */ f = stb_vorbis_open_filename(tiedosto, 0, 0); info = stb_vorbis_get_info(f); stb_vorbis_close(f); /* Tiedot omaan rakenteeseen */ ret.kanavia = info.channels; ret.sampleja_sekunnissa = info.sample_rate; /* Luetaan itse data */ ret.sampleja = stb_vorbis_decode_filename(tiedosto, 0, &ret.data); return ret; } vapauta_aani(struct aani *aani) { free(aani->data); } struct aani koe; koe = lataa_aani("koe.ogg"); soita_aani(&koe); vapauta_aani(&koe);
Näin siis veikkaisin. Soittamiseen tarvitset erillisen kirjaston, kokeile vaikkapa SDL:ää (tai winmm:ää, jos tosiaan siltä tuntuu). Datan asettelua muistissa voit tutkia vaikka itsekin, mutta veikkaisin, että tuossa data
-taulukossa on peräkkäin short-lukuja (etumerkillisiä 16-bittisiä) niin, että peräkkäin on aina yksi sample kutakin kanavaa, kaksikanavaisella siis vuorotellen vasen ja oikea sample. Voit tarkistaa asian tekemällä tiedoston, jonka toinen kanava on tyhjä, ja tulostamalla dataa, jolloin näet, onko joka toinen sample tyhjä.
SDL-soitosta on puhuttu aiemminkin.
Kiitos!! Sain jo jotain kitinää kuulumaan toisesta kaiuttimesta winmm:n kanssa. Mitään SDL:lliä ei tähän nyt sotketa.
#include<windows.h> #include<mmsystem.h> #include "stb_vorbis.c" #define TAVUJA_PER_SAMPLE 2 #define TIEDOSTO "mus.ogg" int main(){ stb_vorbis *f = stb_vorbis_open_filename(TIEDOSTO, 0, 0); stb_vorbis_info info = stb_vorbis_get_info(f); stb_vorbis_close(f); short *data; int turhatemp; int sampleja = stb_vorbis_decode_filename(TIEDOSTO, &turhatemp, &data); WAVEFORMATEX wavinfo = { WAVE_FORMAT_PCM, info.channels, info.sample_rate, info.sample_rate * TAVUJA_PER_SAMPLE * info.channels, TAVUJA_PER_SAMPLE * info.channels, TAVUJA_PER_SAMPLE * 8, 0}; WAVEHDR wav = { (LPSTR)data, sampleja * TAVUJA_PER_SAMPLE, 0, 0, WHDR_BEGINLOOP | WHDR_ENDLOOP, 1, 0, 0}; HWAVEOUT hwo = 0; waveOutOpen(&hwo, WAVE_MAPPER, &wavinfo, 0, 0, 0); waveOutPrepareHeader(hwo, &wav, sizeof(WAVEHDR)); waveOutWrite(hwo, &wav, sizeof(WAVEHDR)); while(!GetAsyncKeyState(VK_ESCAPE)); waveOutReset(hwo); waveOutClose(hwo); free(data); }
Dekoodaus vissiin onnistui, koska sampleja-muuttujan arvo oli sen jälkeen 14509321. Vika on varmaan noissa winmm:n formaattijuttujen asetuksissa. Sekoilin vaan jotain yhden netistä löytyneen koodin ja microsoftin msdn perusteella. Olisko jollakin jotain ideaa miten nuo pitää laittaa? Onko tuo PCM edes oikea formaatti? Tuo koodi pitäs kääntyy helposti, kun laittaa linkkerille -lwinmm.
PCM on kyllä varmaan oikea formaatti, mutta noista funktioista ja niiden parametreistä on kyllä vähän hankala ottaa selkoa. Itse en ainakaan pikaisella googletuksella löytänyt minkäänlaista tutoriaalia aiheesta, joten ei varman auta muu kuin etsiä joku toimiva esimerkkiohjelma ja karsia kaikki ylimääräinen pois niin, että saa oman jutun toimimaan. :)
Kuten Metabolix jo sanoi, kannattaa ainakin aluksi selvittää, onko oggista dekoodattu data oikeassa muodossa winmm:lle. 16-bittiset näytteille on ainakin neljä yleistä enkoodaustapaa (signed/unsigned, big-endian/little-endian). Ja jos kanavia on useampia, niin taas tulee lisää vaihtoehtoja.
SDL helpottaisi asiaa siinä mielessä, että sen käyttöön ainakin löytyy netistä melko selkeät ohjeet. Eikä koodiakaan tulisi paljon tuon enempää.
Aihe on jo aika vanha, joten et voi enää vastata siihen.