From 79c8eb543ef93fbfbc4073c6c4ea71e22e7e02c4 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Thu, 15 Sep 2016 11:53:16 +0200 Subject: [PATCH] Corrected audio bugs and improved examples --- examples/audio_module_playing.c | 30 +++++++++++--- examples/audio_music_stream.c | 53 +++++++++++++------------ src/audio.c | 70 ++++++++++++++++++++------------- 3 files changed, 93 insertions(+), 60 deletions(-) diff --git a/examples/audio_module_playing.c b/examples/audio_module_playing.c index fe9ea15ca..7da3579cc 100644 --- a/examples/audio_module_playing.c +++ b/examples/audio_module_playing.c @@ -62,6 +62,7 @@ int main() PlayMusicStream(xm); float timePlayed = 0.0f; + bool pause = false; SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- @@ -71,7 +72,29 @@ int main() { // Update //---------------------------------------------------------------------------------- - for (int i = MAX_CIRCLES - 1; i >= 0; i--) + UpdateMusicStream(xm); // Update music buffer with new stream data + + // Restart music playing (stop and play) + if (IsKeyPressed(KEY_SPACE)) + { + StopMusicStream(xm); + PlayMusicStream(xm); + } + + // Pause/Resume music playing + if (IsKeyPressed(KEY_P)) + { + pause = !pause; + + if (pause) PauseMusicStream(xm); + else ResumeMusicStream(xm); + } + + // Get timePlayed scaled to bar dimensions + timePlayed = (GetMusicTimePlayed(xm)/GetMusicTimeLength(xm)*(screenWidth - 40))*2; + + // Color circles animation + for (int i = MAX_CIRCLES - 1; (i >= 0) && !pause; i--) { circles[i].alpha += circles[i].speed; circles[i].radius += circles[i].speed*10.0f; @@ -88,11 +111,6 @@ int main() circles[i].speed = (float)GetRandomValue(1, 100)/20000.0f; } } - - // Get timePlayed scaled to bar dimensions - timePlayed = (GetMusicTimePlayed(xm)/GetMusicTimeLength(xm)*(screenWidth - 40))*2; - - UpdateMusicStream(xm); // Update music buffer with new stream data //---------------------------------------------------------------------------------- // Draw diff --git a/examples/audio_music_stream.c b/examples/audio_music_stream.c index c552d0304..dc9d43554 100644 --- a/examples/audio_music_stream.c +++ b/examples/audio_music_stream.c @@ -28,9 +28,8 @@ int main() PlayMusicStream(music); - int framesCounter = 0; float timePlayed = 0.0f; - //float volume = 1.0; + bool pause = false; SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- @@ -40,28 +39,26 @@ int main() { // Update //---------------------------------------------------------------------------------- - framesCounter++; - - // Testing music fading from one file to another -/* - if (framesCounter > 600) // Wait for 10 seconds (600 frames) - { - volume -= 0.01; // Decrement music volume level - - // When music volume level equal or lower than 0, - // restore volume level and init another music file - if (volume <= 0) - { - volume = 1.0; - framesCounter = 0; - } - - SetMusicVolume(volume); - } -*/ - timePlayed = GetMusicTimePlayed(music)/GetMusicTimeLength(music)*100*4; // We scale by 4 to fit 400 pixels - UpdateMusicStream(music); // Update music buffer with new stream data + + // Restart music playing (stop and play) + if (IsKeyPressed(KEY_SPACE)) + { + StopMusicStream(music); + PlayMusicStream(music); + } + + // Pause/Resume music playing + if (IsKeyPressed(KEY_P)) + { + pause = !pause; + + if (pause) PauseMusicStream(music); + else ResumeMusicStream(music); + } + + // Get timePlayed scaled to bar dimensions (400 pixels) + timePlayed = GetMusicTimePlayed(music)/GetMusicTimeLength(music)*100*4; //---------------------------------------------------------------------------------- // Draw @@ -70,10 +67,14 @@ int main() ClearBackground(RAYWHITE); - DrawText("MUSIC SHOULD BE PLAYING!", 255, 200, 20, LIGHTGRAY); + DrawText("MUSIC SHOULD BE PLAYING!", 255, 150, 20, LIGHTGRAY); - DrawRectangle(200, 250, 400, 12, LIGHTGRAY); - DrawRectangle(200, 250, (int)timePlayed, 12, MAROON); + DrawRectangle(200, 200, 400, 12, LIGHTGRAY); + DrawRectangle(200, 200, (int)timePlayed, 12, MAROON); + DrawRectangleLines(200, 200, 400, 12, GRAY); + + DrawText("PRESS SPACE TO RESTART MUSIC", 215, 250, 20, LIGHTGRAY); + DrawText("PRESS P TO PAUSE/RESUME MUSIC", 208, 280, 20, LIGHTGRAY); EndDrawing(); //---------------------------------------------------------------------------------- diff --git a/src/audio.c b/src/audio.c index 06bf55d49..90bf4968e 100644 --- a/src/audio.c +++ b/src/audio.c @@ -225,12 +225,16 @@ Wave LoadWaveEx(float *data, int sampleCount, int sampleRate, int sampleSize, in wave.data = data; wave.sampleCount = sampleCount; wave.sampleRate = sampleRate; - wave.sampleSize = sampleSize; + wave.sampleSize = 32; wave.channels = channels; - WaveFormat(&wave, sampleRate, sampleSize, channels); + // NOTE: Copy wave data to work with, + // user is responsible of input data to free + Wave cwave = WaveCopy(wave); - return wave; + WaveFormat(&cwave, sampleRate, sampleSize, channels); + + return cwave; } // Load sound to memory @@ -578,6 +582,8 @@ void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels) } } else TraceLog(WARNING, "Wave formatting: Sample size not supported"); + + free(samples); } // NOTE: Only supported 1 or 2 channels (mono or stereo) @@ -615,7 +621,8 @@ Wave WaveCopy(Wave wave) // NOTE: Security check in case of out-of-range void WaveCrop(Wave *wave, int initSample, int finalSample) { - if ((initSample >= 0) && (finalSample > 0) && (finalSample < wave->sampleCount)) + if ((initSample >= 0) && (initSample < finalSample) && + (finalSample > 0) && (finalSample < wave->sampleCount)) { // TODO: Review cropping (it could be simplified...) @@ -636,6 +643,7 @@ void WaveCrop(Wave *wave, int initSample, int finalSample) // Get samples data from wave as a floats array // NOTE: Returned sample values are normalized to range [-1..1] +// TODO: Consider multiple channels (mono - stereo) float *GetWaveData(Wave wave) { float *samples = (float *)malloc(wave.sampleCount*sizeof(float)); @@ -759,26 +767,37 @@ void ResumeMusicStream(Music music) } // Stop music playing (close stream) +// TODO: Restart XM context void StopMusicStream(Music music) { alSourceStop(music->stream.source); + + switch (music->ctxType) + { + case MUSIC_AUDIO_OGG: stb_vorbis_seek_start(music->ctxOgg); break; + case MUSIC_MODULE_XM: break; + case MUSIC_MODULE_MOD: jar_mod_seek_start(&music->ctxMod); break; + default: break; + } + + music->samplesLeft = music->totalSamples; } // Update (re-fill) music buffers if data already processed void UpdateMusicStream(Music music) { + ALenum state; ALint processed = 0; - - // Determine if music stream is ready to be written - alGetSourcei(music->stream.source, AL_BUFFERS_PROCESSED, &processed); - - int numBuffersToProcess = processed; + + alGetSourcei(music->stream.source, AL_SOURCE_STATE, &state); // Get music stream state + alGetSourcei(music->stream.source, AL_BUFFERS_PROCESSED, &processed); // Get processed buffers if (processed > 0) { bool active = true; short pcm[AUDIO_BUFFER_SIZE]; float pcmf[AUDIO_BUFFER_SIZE]; + int numBuffersToProcess = processed; int numSamples = 0; // Total size of data steamed in L+R samples for xm floats, // individual L or R for ogg shorts @@ -833,28 +852,23 @@ void UpdateMusicStream(Music music) break; } } - - // Reset audio stream for looping - if (!active && music->loop) - { - // Restart music context (if required) - //if (music->ctxType == MUSIC_MODULE_XM) - if (music->ctxType == MUSIC_MODULE_MOD) jar_mod_seek_start(&music->ctxMod); - else if (music->ctxType == MUSIC_AUDIO_OGG) stb_vorbis_seek_start(music->ctxOgg); - - // Reset samples left to total samples - music->samplesLeft = music->totalSamples; - } - + // This error is registered when UpdateAudioStream() fails if (alGetError() == AL_INVALID_VALUE) TraceLog(WARNING, "OpenAL: Error buffering data..."); - ALenum state; - alGetSourcei(music->stream.source, AL_SOURCE_STATE, &state); - - if (state != AL_PLAYING && active) alSourcePlay(music->stream.source); - - if (!active) StopMusicStream(music); + // Reset audio stream for looping + if (!active) + { + StopMusicStream(music); // Stop music (and reset) + + if (music->loop) PlayMusicStream(music); // Play again + } + else + { + // NOTE: In case window is minimized, music stream is stopped, + // just make sure to play again on window restore + if (state != AL_PLAYING) PlayMusicStream(music); + } } }