diff --git a/examples/audio/audio_module_playing.c b/examples/audio/audio_module_playing.c index 0dae8aa2..557fcb09 100644 --- a/examples/audio/audio_module_playing.c +++ b/examples/audio/audio_module_playing.c @@ -46,13 +46,13 @@ int main(void) circles[i].radius = GetRandomValue(10, 40); circles[i].position.x = GetRandomValue(circles[i].radius, screenWidth - circles[i].radius); circles[i].position.y = GetRandomValue(circles[i].radius, screenHeight - circles[i].radius); - circles[i].speed = (float)GetRandomValue(1, 100)/20000.0f; + circles[i].speed = (float)GetRandomValue(1, 100)/2000.0f; circles[i].color = colors[GetRandomValue(0, 13)]; } - Music xm = LoadMusicStream("resources/chiptun1.mod"); + Music music = LoadMusicStream("resources/mini1111.xm"); - PlayMusicStream(xm); + PlayMusicStream(music); float timePlayed = 0.0f; bool pause = false; @@ -65,13 +65,13 @@ int main(void) { // Update //---------------------------------------------------------------------------------- - UpdateMusicStream(xm); // Update music buffer with new stream data + UpdateMusicStream(music); // Update music buffer with new stream data // Restart music playing (stop and play) if (IsKeyPressed(KEY_SPACE)) { - StopMusicStream(xm); - PlayMusicStream(xm); + StopMusicStream(music); + PlayMusicStream(music); } // Pause/Resume music playing @@ -79,12 +79,12 @@ int main(void) { pause = !pause; - if (pause) PauseMusicStream(xm); - else ResumeMusicStream(xm); + if (pause) PauseMusicStream(music); + else ResumeMusicStream(music); } // Get timePlayed scaled to bar dimensions - timePlayed = GetMusicTimePlayed(xm)/GetMusicTimeLength(xm)*(screenWidth - 40); + timePlayed = GetMusicTimePlayed(music)/GetMusicTimeLength(music)*(screenWidth - 40); // Color circles animation for (int i = MAX_CIRCLES - 1; (i >= 0) && !pause; i--) @@ -101,7 +101,7 @@ int main(void) circles[i].position.x = GetRandomValue(circles[i].radius, screenWidth - circles[i].radius); circles[i].position.y = GetRandomValue(circles[i].radius, screenHeight - circles[i].radius); circles[i].color = colors[GetRandomValue(0, 13)]; - circles[i].speed = (float)GetRandomValue(1, 100)/20000.0f; + circles[i].speed = (float)GetRandomValue(1, 100)/2000.0f; } } //---------------------------------------------------------------------------------- @@ -128,7 +128,7 @@ int main(void) // De-Initialization //-------------------------------------------------------------------------------------- - UnloadMusicStream(xm); // Unload music stream buffers from RAM + UnloadMusicStream(music); // Unload music stream buffers from RAM CloseAudioDevice(); // Close audio device (music streaming is automatically stopped) diff --git a/src/raudio.c b/src/raudio.c index 43e63bc9..2edf660a 100644 --- a/src/raudio.c +++ b/src/raudio.c @@ -124,7 +124,7 @@ // After some math, considering a sampleRate of 48000, a buffer refill rate of 1/60 seconds and a // standard double-buffering system, a 4096 samples buffer has been chosen, it should be enough // In case of music-stalls, just increase this number -#define AUDIO_BUFFER_SIZE 4096 // PCM data samples (i.e. 16bit, Mono: 8Kb) +#define AUDIO_BUFFER_SIZE 4096 // PCM data samples (i.e. 16bit, Mono: 8Kb) //---------------------------------------------------------------------------------- // Types and Structures Definition @@ -189,6 +189,8 @@ void TraceLog(int msgType, const char *text, ...); // Show trace lo #define DEVICE_CHANNELS 2 #define DEVICE_SAMPLE_RATE 44100 +#define MAX_AUDIO_BUFFER_POOL_CHANNELS 16 + typedef enum { AUDIO_BUFFER_USAGE_STATIC = 0, AUDIO_BUFFER_USAGE_STREAM } AudioBufferUsage; // Audio buffer structure @@ -205,16 +207,22 @@ struct rAudioBuffer { bool looping; // Audio buffer looping, always true for AudioStreams int usage; // Audio buffer usage mode: STATIC or STREAM - bool isSubBufferProcessed[2]; - unsigned int frameCursorPos; // Samples processed? - unsigned int bufferSizeInFrames; + bool isSubBufferProcessed[2]; // SubBuffer processed (virtual double buffer) + unsigned int frameCursorPos; // Frame cursor position + unsigned int bufferSizeInFrames; // Total buffer size in frames + unsigned int totalFramesProcessed; // Total frames processed in this buffer (required for play timming) - rAudioBuffer *next; - rAudioBuffer *prev; - unsigned char *buffer; + unsigned char *buffer; // Data buffer, on music stream keeps filling + + rAudioBuffer *next; // Next audio buffer on the list + rAudioBuffer *prev; // Previous audio buffer on the list }; -#define AudioBuffer rAudioBuffer // HACK: To avoid CoreAudio (macOS) symbol collision +#define AudioBuffer rAudioBuffer // HACK: To avoid CoreAudio (macOS) symbol collision + +// Audio buffers are tracked in a linked list +static AudioBuffer *firstAudioBuffer = NULL; +static AudioBuffer *lastAudioBuffer = NULL; // miniaudio global variables static ma_context context; @@ -223,9 +231,10 @@ static ma_mutex audioLock; static bool isAudioInitialized = false; static float masterVolume = 1.0f; -// Audio buffers are tracked in a linked list -static AudioBuffer *firstAudioBuffer = NULL; -static AudioBuffer *lastAudioBuffer = NULL; +// Multi channel playback global variables +AudioBuffer *audioBufferPool[MAX_AUDIO_BUFFER_POOL_CHANNELS] = { 0 }; +unsigned int audioBufferPoolCounter = 0; +unsigned int audioBufferPoolChannels[MAX_AUDIO_BUFFER_POOL_CHANNELS] = { 0 }; // miniaudio functions declaration static void OnLog(ma_context *pContext, ma_device *pDevice, ma_uint32 logLevel, const char *message); @@ -247,19 +256,9 @@ void SetAudioBufferPitch(AudioBuffer *buffer, float pitch); void TrackAudioBuffer(AudioBuffer *buffer); void UntrackAudioBuffer(AudioBuffer *buffer); -//---------------------------------------------------------------------------------- -// Multi channel playback globals -//---------------------------------------------------------------------------------- -// Number of channels in the audio pool -#define MAX_AUDIO_BUFFER_POOL_CHANNELS 16 - -// Audio buffer pool -AudioBuffer *audioBufferPool[MAX_AUDIO_BUFFER_POOL_CHANNELS] = { 0 }; - -// These are used to determine the oldest playing channel -unsigned long audioBufferPoolCounter = 0; -unsigned long audioBufferPoolChannels[MAX_AUDIO_BUFFER_POOL_CHANNELS] = { 0 }; +//---------------------------------------------------------------------------------- +// miniaudio functions definitions //---------------------------------------------------------------------------------- // Log callback function @@ -319,6 +318,7 @@ static void OnSendAudioDataToDevice(ma_device *pDevice, void *pFramesOut, const { float *framesOut = (float *)pFramesOut + (framesRead*device.playback.channels); float *framesIn = tempBuffer; + MixAudioFrames(framesOut, framesIn, framesJustRead, audioBuffer->volume); framesToRead -= framesJustRead; @@ -485,7 +485,6 @@ void InitAudioDevice(void) { // Init audio context ma_context_config contextConfig = ma_context_config_init(); - contextConfig.logCallback = OnLog; ma_result result = ma_context_init(NULL, 0, &contextConfig, &context); @@ -553,11 +552,7 @@ void InitAudioDevice(void) // Close the audio device for all contexts void CloseAudioDevice(void) { - if (!isAudioInitialized) - { - TraceLog(LOG_WARNING, "Could not close audio device because it is not currently initialized"); - } - else + if (isAudioInitialized) { ma_mutex_uninit(&audioLock); ma_device_uninit(&device); @@ -567,6 +562,7 @@ void CloseAudioDevice(void) TraceLog(LOG_INFO, "Audio device closed successfully"); } + else TraceLog(LOG_WARNING, "Could not close audio device because it is not currently initialized"); } // Check if device has been initialized successfully @@ -588,11 +584,11 @@ void SetMasterVolume(float volume) // Module Functions Definition - Audio Buffer management //---------------------------------------------------------------------------------- -// Create a new audio buffer. Initially filled with silence +// Initialize a new audio buffer (filled with silence) AudioBuffer *InitAudioBuffer(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, ma_uint32 bufferSizeInFrames, int usage) { AudioBuffer *audioBuffer = (AudioBuffer *)RL_CALLOC(1, sizeof(AudioBuffer)); - audioBuffer->buffer = RL_CALLOC((bufferSizeInFrames*channels*ma_get_bytes_per_sample(format)), 1); + audioBuffer->buffer = RL_CALLOC(bufferSizeInFrames*channels*ma_get_bytes_per_sample(format), 1); if (audioBuffer == NULL) { @@ -690,6 +686,7 @@ void StopAudioBuffer(AudioBuffer *buffer) buffer->playing = false; buffer->paused = false; buffer->frameCursorPos = 0; + buffer->totalFramesProcessed = 0; buffer->isSubBufferProcessed[0] = true; buffer->isSubBufferProcessed[1] = true; } @@ -725,8 +722,10 @@ void SetAudioBufferPitch(AudioBuffer *buffer, float pitch) { float pitchMul = pitch/buffer->pitch; - // Pitching is just an adjustment of the sample rate. Note that this changes the duration of the sound - higher pitches - // will make the sound faster; lower pitches make it slower. + // Pitching is just an adjustment of the sample rate. + // Note that this changes the duration of the sound: + // - higher pitches will make the sound faster + // - lower pitches make it slower ma_uint32 newOutputSampleRate = (ma_uint32)((float)buffer->dsp.src.config.sampleRateOut/pitchMul); buffer->pitch *= (float)buffer->dsp.src.config.sampleRateOut/newOutputSampleRate; @@ -869,16 +868,14 @@ void UpdateSound(Sound sound, const void *data, int samplesCount) { AudioBuffer *audioBuffer = sound.stream.buffer; - if (audioBuffer == NULL) + if (audioBuffer != NULL) { - TraceLog(LOG_ERROR, "UpdateSound() : Invalid sound - no audio buffer"); - return; - } - - StopAudioBuffer(audioBuffer); + StopAudioBuffer(audioBuffer); - // TODO: May want to lock/unlock this since this data buffer is read at mixing time - memcpy(audioBuffer->buffer, data, samplesCount*audioBuffer->dsp.formatConverterIn.config.channels*ma_get_bytes_per_sample(audioBuffer->dsp.formatConverterIn.config.formatIn)); + // TODO: May want to lock/unlock this since this data buffer is read at mixing time + memcpy(audioBuffer->buffer, data, samplesCount*audioBuffer->dsp.formatConverterIn.config.channels*ma_get_bytes_per_sample(audioBuffer->dsp.formatConverterIn.config.formatIn)); + } + else TraceLog(LOG_ERROR, "UpdateSound() : Invalid sound - no audio buffer"); } // Export wave data to file @@ -956,7 +953,7 @@ void PlaySound(Sound sound) void PlaySoundMulti(Sound sound) { int index = -1; - unsigned long oldAge = 0; + unsigned int oldAge = 0; int oldIndex = -1; // find the first non playing pool entry @@ -1184,14 +1181,8 @@ Music LoadMusicStream(const char *fileName) // OGG bit rate defaults to 16 bit, it's enough for compressed format music.stream = InitAudioStream(info.sample_rate, 16, info.channels); music.sampleCount = (unsigned int)stb_vorbis_stream_length_in_samples((stb_vorbis *)music.ctxData)*info.channels; - music.sampleLeft = music.sampleCount; music.loopCount = 0; // Infinite loop by default musicLoaded = true; - - TraceLog(LOG_INFO, "[%s] OGG total samples: %i", fileName, music.sampleCount); - TraceLog(LOG_INFO, "[%s] OGG sample rate: %i", fileName, info.sample_rate); - TraceLog(LOG_INFO, "[%s] OGG channels: %i", fileName, info.channels); - TraceLog(LOG_INFO, "[%s] OGG memory required: %i", fileName, info.temp_memory_required); } } #endif @@ -1207,14 +1198,8 @@ Music LoadMusicStream(const char *fileName) music.stream = InitAudioStream(ctxFlac->sampleRate, ctxFlac->bitsPerSample, ctxFlac->channels); music.sampleCount = (unsigned int)ctxFlac->totalSampleCount; - music.sampleLeft = music.sampleCount; music.loopCount = 0; // Infinite loop by default musicLoaded = true; - - TraceLog(LOG_DEBUG, "[%s] FLAC total samples: %i", fileName, music.sampleCount); - TraceLog(LOG_DEBUG, "[%s] FLAC sample rate: %i", fileName, ctxFlac->sampleRate); - TraceLog(LOG_DEBUG, "[%s] FLAC bits per sample: %i", fileName, ctxFlac->bitsPerSample); - TraceLog(LOG_DEBUG, "[%s] FLAC channels: %i", fileName, ctxFlac->channels); } } #endif @@ -1232,14 +1217,8 @@ Music LoadMusicStream(const char *fileName) music.stream = InitAudioStream(ctxMp3->sampleRate, 32, ctxMp3->channels); music.sampleCount = drmp3_get_pcm_frame_count(ctxMp3)*ctxMp3->channels; - music.sampleLeft = music.sampleCount; music.loopCount = 0; // Infinite loop by default musicLoaded = true; - - TraceLog(LOG_INFO, "[%s] MP3 sample rate: %i", fileName, ctxMp3->sampleRate); - TraceLog(LOG_INFO, "[%s] MP3 bits per sample: %i", fileName, 32); - TraceLog(LOG_INFO, "[%s] MP3 channels: %i", fileName, ctxMp3->channels); - TraceLog(LOG_INFO, "[%s] MP3 total samples: %i", fileName, music.sampleCount); } } #endif @@ -1258,14 +1237,10 @@ Music LoadMusicStream(const char *fileName) // NOTE: Only stereo is supported for XM music.stream = InitAudioStream(48000, 16, 2); music.sampleCount = (unsigned int)jar_xm_get_remaining_samples(ctxXm); - music.sampleLeft = music.sampleCount; music.loopCount = 0; // Infinite loop by default musicLoaded = true; music.ctxData = ctxXm; - - TraceLog(LOG_INFO, "[%s] XM number of samples: %i", fileName, music.sampleCount); - TraceLog(LOG_INFO, "[%s] XM track length: %11.6f sec", fileName, (float)music.sampleCount/48000.0f); } } #endif @@ -1285,12 +1260,8 @@ Music LoadMusicStream(const char *fileName) // NOTE: Only stereo is supported for MOD music.stream = InitAudioStream(48000, 16, 2); music.sampleCount = (unsigned int)jar_mod_max_samples(ctxMod); - music.sampleLeft = music.sampleCount; music.loopCount = 0; // Infinite loop by default musicLoaded = true; - - TraceLog(LOG_INFO, "[%s] MOD number of samples: %i", fileName, music.sampleCount); - TraceLog(LOG_INFO, "[%s] MOD track length: %11.6f sec", fileName, (float)music.sampleCount/48000.0f); } } #endif @@ -1316,6 +1287,15 @@ Music LoadMusicStream(const char *fileName) TraceLog(LOG_WARNING, "[%s] Music file could not be opened", fileName); } + else + { + // Show some music stream info + TraceLog(LOG_INFO, "[%s] Music file successfully loaded:", fileName); + TraceLog(LOG_INFO, " Total samples: %i", music.sampleCount); + TraceLog(LOG_INFO, " Sample rate: %i Hz", music.stream.sampleRate); + TraceLog(LOG_INFO, " Sample size: %i bits", music.stream.sampleSize); + TraceLog(LOG_INFO, " Channels: %i (%s)", music.stream.channels, (music.stream.channels == 1)? "Mono" : (music.stream.channels == 2)? "Stereo" : "Multi"); + } return music; } @@ -1348,21 +1328,18 @@ void PlayMusicStream(Music music) { AudioBuffer *audioBuffer = music.stream.buffer; - if (audioBuffer == NULL) + if (audioBuffer != NULL) { - TraceLog(LOG_ERROR, "PlayMusicStream() : No audio buffer"); - return; + // For music streams, we need to make sure we maintain the frame cursor position + // This is a hack for this section of code in UpdateMusicStream() + // NOTE: In case window is minimized, music stream is stopped, just make sure to + // play again on window restore: if (IsMusicPlaying(music)) PlayMusicStream(music); + ma_uint32 frameCursorPos = audioBuffer->frameCursorPos; + PlayAudioStream(music.stream); // WARNING: This resets the cursor position. + audioBuffer->frameCursorPos = frameCursorPos; } + else TraceLog(LOG_ERROR, "PlayMusicStream() : No audio buffer"); - // For music streams, we need to make sure we maintain the frame cursor position - // This is a hack for this section of code in UpdateMusicStream() - // NOTE: In case window is minimized, music stream is stopped, just make sure to - // play again on window restore: if (IsMusicPlaying(music)) PlayMusicStream(music); - ma_uint32 frameCursorPos = audioBuffer->frameCursorPos; - - PlayAudioStream(music.stream); // <-- This resets the cursor position. - - audioBuffer->frameCursorPos = frameCursorPos; } // Pause music playing @@ -1389,7 +1366,7 @@ void StopMusicStream(Music music) case MUSIC_AUDIO_OGG: stb_vorbis_seek_start((stb_vorbis *)music.ctxData); break; #endif #if defined(SUPPORT_FILEFORMAT_FLAC) - case MUSIC_AUDIO_FLAC: /* TODO: Restart FLAC context */ break; + case MUSIC_AUDIO_FLAC: drflac_seek_to_sample((drflac *)music.ctxData, 0) break; #endif #if defined(SUPPORT_FILEFORMAT_MP3) case MUSIC_AUDIO_MP3: drmp3_seek_to_pcm_frame((drmp3 *)music.ctxData, 0); break; @@ -1402,8 +1379,6 @@ void StopMusicStream(Music music) #endif default: break; } - - music.sampleLeft = music.sampleCount; } // Update (re-fill) music buffers if data already processed @@ -1416,12 +1391,16 @@ void UpdateMusicStream(Music music) // NOTE: Using dynamic allocation because it could require more than 16KB void *pcm = RL_CALLOC(subBufferSizeInFrames*music.stream.channels*music.stream.sampleSize/8, 1); - int samplesCount = 0; // Total size of data steamed in L+R samples for xm floats, individual L or R for ogg shorts + int samplesCount = 0; // Total size of data streamed in L+R samples for xm floats, individual L or R for ogg shorts + + // TODO: Get the sampleLeft using totalFramesProcessed... but first, get total frames processed correctly... + //ma_uint32 frameSizeInBytes = ma_get_bytes_per_sample(music.stream.buffer->dsp.formatConverterIn.config.formatIn)*music.stream.buffer->dsp.formatConverterIn.config.channels; + int sampleLeft = music.sampleCount - (music.stream.buffer->totalFramesProcessed*music.stream.channels); while (IsAudioStreamProcessed(music.stream)) { - if ((music.sampleLeft/music.stream.channels) >= subBufferSizeInFrames) samplesCount = subBufferSizeInFrames*music.stream.channels; - else samplesCount = music.sampleLeft; + if ((sampleLeft/music.stream.channels) >= subBufferSizeInFrames) samplesCount = subBufferSizeInFrames*music.stream.channels; + else samplesCount = sampleLeft; switch (music.ctxType) { @@ -1470,12 +1449,12 @@ void UpdateMusicStream(Music music) if ((music.ctxType == MUSIC_MODULE_XM) || (music.ctxType == MUSIC_MODULE_MOD)) { - if (samplesCount > 1) music.sampleLeft -= samplesCount/2; - else music.sampleLeft -= samplesCount; + if (samplesCount > 1) sampleLeft -= samplesCount/2; + else sampleLeft -= samplesCount; } - else music.sampleLeft -= samplesCount; + else sampleLeft -= samplesCount; - if (music.sampleLeft <= 0) + if (sampleLeft <= 0) { streamEnding = true; break; @@ -1493,13 +1472,10 @@ void UpdateMusicStream(Music music) // Decrease loopCount to stop when required if (music.loopCount > 1) { - music.loopCount--; // Decrease loop count + music.loopCount--; // Decrease loop count PlayMusicStream(music); // Play again } - else - { - if (music.loopCount == 0) PlayMusicStream(music); - } + else if (music.loopCount == 0) PlayMusicStream(music); } else { @@ -1549,7 +1525,8 @@ float GetMusicTimePlayed(Music music) { float secondsPlayed = 0.0f; - unsigned int samplesPlayed = music.sampleCount - music.sampleLeft; + //ma_uint32 frameSizeInBytes = ma_get_bytes_per_sample(music.stream.buffer->dsp.formatConverterIn.config.formatIn)*music.stream.buffer->dsp.formatConverterIn.config.channels; + unsigned int samplesPlayed = music.stream.buffer->totalFramesProcessed*music.stream.channels; secondsPlayed = (float)samplesPlayed/(music.stream.sampleRate*music.stream.channels); return secondsPlayed; @@ -1562,14 +1539,7 @@ AudioStream InitAudioStream(unsigned int sampleRate, unsigned int sampleSize, un stream.sampleRate = sampleRate; stream.sampleSize = sampleSize; - - // Only mono and stereo channels are supported - if ((channels > 0) && (channels < 3)) stream.channels = channels; - else - { - TraceLog(LOG_WARNING, "Init audio stream: Number of channels not supported: %i", channels); - stream.channels = 1; // Fallback to mono channel - } + stream.channels = channels; ma_format formatIn = ((stream.sampleSize == 8)? ma_format_u8 : ((stream.sampleSize == 16)? ma_format_s16 : ma_format_f32)); @@ -1579,18 +1549,14 @@ AudioStream InitAudioStream(unsigned int sampleRate, unsigned int sampleSize, un if (subBufferSize < periodSize) subBufferSize = periodSize; - AudioBuffer *audioBuffer = InitAudioBuffer(formatIn, stream.channels, stream.sampleRate, subBufferSize*2, AUDIO_BUFFER_USAGE_STREAM); + stream.buffer = InitAudioBuffer(formatIn, stream.channels, stream.sampleRate, subBufferSize*2, AUDIO_BUFFER_USAGE_STREAM); - if (audioBuffer == NULL) + if (stream.buffer != NULL) { - TraceLog(LOG_ERROR, "InitAudioStream() : Failed to create audio buffer"); - return stream; + stream.buffer->looping = true; // Always loop for streaming buffers + TraceLog(LOG_INFO, "Audio stream loaded successfully (%i Hz, %i bit, %s)", stream.sampleRate, stream.sampleSize, (stream.channels == 1)? "Mono" : "Stereo"); } - - audioBuffer->looping = true; // Always loop for streaming buffers - stream.buffer = audioBuffer; - - TraceLog(LOG_INFO, "Audio stream loaded successfully (%i Hz, %i bit, %s)", stream.sampleRate, stream.sampleSize, (stream.channels == 1)? "Mono" : "Stereo"); + else TraceLog(LOG_ERROR, "InitAudioStream() : Failed to create audio buffer"); return stream; } @@ -1610,56 +1576,54 @@ void UpdateAudioStream(AudioStream stream, const void *data, int samplesCount) { AudioBuffer *audioBuffer = stream.buffer; - if (audioBuffer == NULL) + if (audioBuffer != NULL) { - TraceLog(LOG_ERROR, "UpdateAudioStream() : No audio buffer"); - return; - } + if (audioBuffer->isSubBufferProcessed[0] || audioBuffer->isSubBufferProcessed[1]) + { + ma_uint32 subBufferToUpdate = 0; - if (audioBuffer->isSubBufferProcessed[0] || audioBuffer->isSubBufferProcessed[1]) - { - ma_uint32 subBufferToUpdate = 0; + if (audioBuffer->isSubBufferProcessed[0] && audioBuffer->isSubBufferProcessed[1]) + { + // Both buffers are available for updating. + // Update the first one and make sure the cursor is moved back to the front. + subBufferToUpdate = 0; + audioBuffer->frameCursorPos = 0; + } + else + { + // Just update whichever sub-buffer is processed. + subBufferToUpdate = (audioBuffer->isSubBufferProcessed[0])? 0 : 1; + } - if (audioBuffer->isSubBufferProcessed[0] && audioBuffer->isSubBufferProcessed[1]) - { - // Both buffers are available for updating. - // Update the first one and make sure the cursor is moved back to the front. - subBufferToUpdate = 0; - audioBuffer->frameCursorPos = 0; - } - else - { - // Just update whichever sub-buffer is processed. - subBufferToUpdate = (audioBuffer->isSubBufferProcessed[0])? 0 : 1; - } + ma_uint32 subBufferSizeInFrames = audioBuffer->bufferSizeInFrames/2; + unsigned char *subBuffer = audioBuffer->buffer + ((subBufferSizeInFrames*stream.channels*(stream.sampleSize/8))*subBufferToUpdate); - ma_uint32 subBufferSizeInFrames = audioBuffer->bufferSizeInFrames/2; - unsigned char *subBuffer = audioBuffer->buffer + ((subBufferSizeInFrames*stream.channels*(stream.sampleSize/8))*subBufferToUpdate); + // TODO: Get total frames processed on this buffer... DOES NOT WORK. + audioBuffer->totalFramesProcessed += subBufferSizeInFrames; - // Does this API expect a whole buffer to be updated in one go? - // Assuming so, but if not will need to change this logic. - if (subBufferSizeInFrames >= (ma_uint32)samplesCount/stream.channels) - { - ma_uint32 framesToWrite = subBufferSizeInFrames; + // Does this API expect a whole buffer to be updated in one go? + // Assuming so, but if not will need to change this logic. + if (subBufferSizeInFrames >= (ma_uint32)samplesCount/stream.channels) + { + ma_uint32 framesToWrite = subBufferSizeInFrames; - if (framesToWrite > ((ma_uint32)samplesCount/stream.channels)) framesToWrite = (ma_uint32)samplesCount/stream.channels; + if (framesToWrite > ((ma_uint32)samplesCount/stream.channels)) framesToWrite = (ma_uint32)samplesCount/stream.channels; - ma_uint32 bytesToWrite = framesToWrite*stream.channels*(stream.sampleSize/8); - memcpy(subBuffer, data, bytesToWrite); + ma_uint32 bytesToWrite = framesToWrite*stream.channels*(stream.sampleSize/8); + memcpy(subBuffer, data, bytesToWrite); - // Any leftover frames should be filled with zeros. - ma_uint32 leftoverFrameCount = subBufferSizeInFrames - framesToWrite; + // Any leftover frames should be filled with zeros. + ma_uint32 leftoverFrameCount = subBufferSizeInFrames - framesToWrite; - if (leftoverFrameCount > 0) - { - memset(subBuffer + bytesToWrite, 0, leftoverFrameCount*stream.channels*(stream.sampleSize/8)); - } + if (leftoverFrameCount > 0) memset(subBuffer + bytesToWrite, 0, leftoverFrameCount*stream.channels*(stream.sampleSize/8)); - audioBuffer->isSubBufferProcessed[subBufferToUpdate] = false; + audioBuffer->isSubBufferProcessed[subBufferToUpdate] = false; + } + else TraceLog(LOG_ERROR, "UpdateAudioStream() : Attempting to write too many frames to buffer"); } - else TraceLog(LOG_ERROR, "UpdateAudioStream() : Attempting to write too many frames to buffer"); + else TraceLog(LOG_ERROR, "UpdateAudioStream() : Audio buffer not available for updating"); } - else TraceLog(LOG_ERROR, "Audio buffer not available for updating"); + else TraceLog(LOG_ERROR, "UpdateAudioStream() : No audio buffer"); } // Check if any audio stream buffers requires refill diff --git a/src/raudio.h b/src/raudio.h index 302993a9..e508d380 100644 --- a/src/raudio.h +++ b/src/raudio.h @@ -1,6 +1,6 @@ /********************************************************************************************** * -* raudio - A simple and easy-to-use audio library based on mini_al +* raudio - A simple and easy-to-use audio library based on miniaudio * * FEATURES: * - Manage audio device (init/close) @@ -20,7 +20,7 @@ * * CONTRIBUTORS: * David Reid (github: @mackron) (Nov. 2017): -* - Complete port to mini_al library +* - Complete port to miniaudio library * * Joshua Reisenauer (github: @kd7tck) (2015) * - XM audio module support (jar_xm) diff --git a/src/raylib.h b/src/raylib.h index ec6fd8a1..ed0314d3 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -434,7 +434,6 @@ typedef struct Music { void *ctxData; // Audio context data, depends on type unsigned int sampleCount; // Total number of samples - unsigned int sampleLeft; // Number of samples left to end unsigned int loopCount; // Loops count (times music will play), 0 means infinite loop AudioStream stream; // Audio stream