2016-06-28 3 views
0

Quel que soit le fichier audio que j'utilise, il coupe toujours environ un quart de la longueur. J'ai l'impression que c'est parce que je lance l'audio décodé vers un Uint8*, mais si ce n'est pas le cas, l'audio joue très vite et ne joue toujours que la moitié du fichier. En outre, l'utilisation de SDL_MixAudio au lieu de SDL_memcpy provoque la lecture d'un groupe de copies du son pour une raison quelconque.Lecture audio avec stb_vorbis et SDL2 coupées

Uint8* audio_pos; 
Uint32 audio_len; 

void audioCallback(void* userdata, Uint8* stream, int len) { 
    if (audio_len == 0) return; 
    len = (len > audio_len ? audio_len : len); 
    SDL_memcpy(stream, audio_pos, len); 
    audio_pos += len; 
    audio_len -= len; 
} 

int main(int argc, char *argv[]) { 
    ... 
    short* decoded; 
    int channels, rate, len; 
    len = stb_vorbis_decode_filename(RealPath("music.ogg").c_str(), &channels, &rate, &decoded); 

    SDL_AudioSpec spec; 
    spec.freq = rate; 
    spec.format = AUDIO_S16; 
    spec.channels = channels; 
    spec.samples = 2048; 
    spec.callback = audioCallback; 
    spec.userdata = NULL; 

    audio_pos = (Uint8*)decoded; 
    audio_len = len; 

    if (SDL_OpenAudio(&spec, NULL) < 0) { 
     std::cout << "failed to open audio device: " << SDL_GetError() << '\n'; 
     SDL_GL_DeleteContext(context); 
     SDL_Quit(); 
     return -1; 
    } 

    SDL_PauseAudio(0); 

    SDL_Event windowEvt; 
    while (true) { 
     if (audio_len == 0) break; 
     if (SDL_PollEvent(&windowEvt)) { 
      if (windowEvt.type == SDL_QUIT) break; 
      if (windowEvt.type == SDL_KEYUP && windowEvt.key.keysym.sym == SDLK_ESCAPE) break; 
     } 
     SDL_GL_SwapWindow(window); 
    } 
    ... 
} 

Répondre

0

stb_vorbis_decode_filename renvoie le « nombre d'échantillons décodés, » qui est rapport à un int16, et ne comprend pas le facteur de canal. Vous êtes à la recherche:

int32 length = stb_vorbis_decode_filename("thing.ogg", &channels, &rate, &decoded); 
int32 audio_length = length * channels * (sizeof(int16)/sizeof(uint8)); 

En ce qui concerne SDL_MixAudio vs SDL_memcpy de chevauchement du son, vous devez effacer explicitement le flux avec une valeur de silence. Par exemple, SDL_memset lorsque vous entrez le rappel audio SDL.

void audioCallback(void* userdata, Uint8* stream, int len) 
{ 
    SDL_memset(stream, 0, len);// silence the stream 
    if (audio_len == 0) return; 
    len = (len > audio_len ? audio_len : len); 
    SDL_MixAudio(stream, audio_pos, len, SDL_MIX_MAXVOLUME);// this takes a volume argument 
    audio_pos += len; 
    audio_len -= len; 
} 

Le zéro est passé à SDL_memset devrait être la valeur même de silence que vous avez créé dans SDL_AudioSpec, lors de l'appel SDL_OpenAudioDevice.