diff options
| author | DarkElvenAngel <[email protected]> | 2019-06-10 16:12:06 -0400 |
|---|---|---|
| committer | GitHub <[email protected]> | 2019-06-10 16:12:06 -0400 |
| commit | d7f4be071579e6f00974c0940f021272f22fbc54 (patch) | |
| tree | 6ee389e6617c494d272e9bc82415fbc3618e7a28 /src/raudio.c | |
| parent | 8a21830b77eaa76ffe0c31df5f96aecd6bd2eecc (diff) | |
| parent | baf7d7d19ad8d6bfbfc201169e4ed4f49a9576a6 (diff) | |
| download | raylib-d7f4be071579e6f00974c0940f021272f22fbc54.tar.gz raylib-d7f4be071579e6f00974c0940f021272f22fbc54.zip | |
Merge pull request #1 from raysan5/master
Update
Diffstat (limited to 'src/raudio.c')
| -rw-r--r-- | src/raudio.c | 312 |
1 files changed, 160 insertions, 152 deletions
diff --git a/src/raudio.c b/src/raudio.c index b19c7d86..6ac0110c 100644 --- a/src/raudio.c +++ b/src/raudio.c @@ -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) @@ -26,7 +26,7 @@ * supported by default, to remove support, just comment unrequired #define in this module * * DEPENDENCIES: -* mini_al.h - Audio device management lib (https://github.com/dr-soft/mini_al) +* miniaudio.h - Audio device management lib (https://github.com/dr-soft/miniaudio) * stb_vorbis.h - Ogg audio files loading (http://www.nothings.org/stb_vorbis/) * dr_mp3.h - MP3 audio file loading (https://github.com/mackron/dr_libs) * dr_flac.h - FLAC audio file loading (https://github.com/mackron/dr_libs) @@ -35,7 +35,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) @@ -46,7 +46,7 @@ * * LICENSE: zlib/libpng * -* Copyright (c) 2014-2019 Ramon Santamaria (@raysan5) +* Copyright (c) 2013-2019 Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event * will the authors be held liable for any damages arising from the use of this software. @@ -77,11 +77,9 @@ #include "utils.h" // Required for: fopen() Android mapping #endif -#define MAL_NO_SDL -#define MAL_NO_JACK -#define MAL_NO_OPENAL -#define MINI_AL_IMPLEMENTATION -#include "external/mini_al.h" // mini_al audio library +#define MA_NO_JACK +#define MINIAUDIO_IMPLEMENTATION +#include "external/miniaudio.h" // miniaudio library #undef PlaySound // Win32 API: windows.h > mmsystem.h defines PlaySound macro #include <stdlib.h> // Required for: malloc(), free() @@ -208,9 +206,9 @@ void TraceLog(int msgType, const char *text, ...); // Show trace lo #endif //---------------------------------------------------------------------------------- -// mini_al AudioBuffer Functionality +// miniaudio AudioBuffer Functionality //---------------------------------------------------------------------------------- -#define DEVICE_FORMAT mal_format_f32 +#define DEVICE_FORMAT ma_format_f32 #define DEVICE_CHANNELS 2 #define DEVICE_SAMPLE_RATE 44100 @@ -220,7 +218,7 @@ typedef enum { AUDIO_BUFFER_USAGE_STATIC = 0, AUDIO_BUFFER_USAGE_STREAM } AudioB // NOTE: Slightly different logic is used when feeding data to the playback device depending on whether or not data is streamed typedef struct rAudioBuffer rAudioBuffer; struct rAudioBuffer { - mal_dsp dsp; // Required for format conversion + ma_pcm_converter dsp; // Required for format conversion float volume; float pitch; bool playing; @@ -239,26 +237,26 @@ struct rAudioBuffer { // NOTE: This system should probably be redesigned #define AudioBuffer rAudioBuffer -// mini_al global variables -static mal_context context; -static mal_device device; -static mal_mutex audioLock; -static bool isAudioInitialized = MAL_FALSE; +// miniaudio global variables +static ma_context context; +static ma_device device; +static ma_mutex audioLock; +static bool isAudioInitialized = MA_FALSE; static float masterVolume = 1.0f; // Audio buffers are tracked in a linked list static AudioBuffer *firstAudioBuffer = NULL; static AudioBuffer *lastAudioBuffer = NULL; -// mini_al functions declaration -static void OnLog(mal_context *pContext, mal_device *pDevice, const char *message); -static mal_uint32 OnSendAudioDataToDevice(mal_device *pDevice, mal_uint32 frameCount, void *pFramesOut); -static mal_uint32 OnAudioBufferDSPRead(mal_dsp *pDSP, mal_uint32 frameCount, void *pFramesOut, void *pUserData); -static void MixAudioFrames(float *framesOut, const float *framesIn, mal_uint32 frameCount, float localVolume); +// miniaudio functions declaration +static void OnLog(ma_context *pContext, ma_device *pDevice, ma_uint32 logLevel, const char *message); +static void OnSendAudioDataToDevice(ma_device *pDevice, void *pFramesOut, const void *pFramesInput, ma_uint32 frameCount); +static ma_uint32 OnAudioBufferDSPRead(ma_pcm_converter *pDSP, void *pFramesOut, ma_uint32 frameCount, void *pUserData); +static void MixAudioFrames(float *framesOut, const float *framesIn, ma_uint32 frameCount, float localVolume); // AudioBuffer management functions declaration // NOTE: Those functions are not exposed by raylib... for the moment -AudioBuffer *CreateAudioBuffer(mal_format format, mal_uint32 channels, mal_uint32 sampleRate, mal_uint32 bufferSizeInFrames, AudioBufferUsage usage); +AudioBuffer *CreateAudioBuffer(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, ma_uint32 bufferSizeInFrames, AudioBufferUsage usage); void DeleteAudioBuffer(AudioBuffer *audioBuffer); bool IsAudioBufferPlaying(AudioBuffer *audioBuffer); void PlayAudioBuffer(AudioBuffer *audioBuffer); @@ -270,35 +268,34 @@ void SetAudioBufferPitch(AudioBuffer *audioBuffer, float pitch); void TrackAudioBuffer(AudioBuffer *audioBuffer); void UntrackAudioBuffer(AudioBuffer *audioBuffer); - // Log callback function -static void OnLog(mal_context *pContext, mal_device *pDevice, const char *message) +static void OnLog(ma_context *pContext, ma_device *pDevice, ma_uint32 logLevel, const char *message) { (void)pContext; (void)pDevice; - TraceLog(LOG_ERROR, message); // All log messages from mini_al are errors + TraceLog(LOG_ERROR, message); // All log messages from miniaudio are errors } // Sending audio data to device callback function -static mal_uint32 OnSendAudioDataToDevice(mal_device *pDevice, mal_uint32 frameCount, void *pFramesOut) +static void OnSendAudioDataToDevice(ma_device *pDevice, void *pFramesOut, const void *pFramesInput, ma_uint32 frameCount) { // This is where all of the mixing takes place. (void)pDevice; // Mixing is basically just an accumulation. We need to initialize the output buffer to 0. - memset(pFramesOut, 0, frameCount*pDevice->channels*mal_get_bytes_per_sample(pDevice->format)); + memset(pFramesOut, 0, frameCount*pDevice->playback.channels*ma_get_bytes_per_sample(pDevice->playback.format)); // Using a mutex here for thread-safety which makes things not real-time. This is unlikely to be necessary for this project, but may // want to consider how you might want to avoid this. - mal_mutex_lock(&audioLock); + ma_mutex_lock(&audioLock); { for (AudioBuffer *audioBuffer = firstAudioBuffer; audioBuffer != NULL; audioBuffer = audioBuffer->next) { // Ignore stopped or paused sounds. if (!audioBuffer->playing || audioBuffer->paused) continue; - mal_uint32 framesRead = 0; + ma_uint32 framesRead = 0; for (;;) { if (framesRead > frameCount) @@ -310,21 +307,21 @@ static mal_uint32 OnSendAudioDataToDevice(mal_device *pDevice, mal_uint32 frameC if (framesRead == frameCount) break; // Just read as much data as we can from the stream. - mal_uint32 framesToRead = (frameCount - framesRead); + ma_uint32 framesToRead = (frameCount - framesRead); while (framesToRead > 0) { float tempBuffer[1024]; // 512 frames for stereo. - mal_uint32 framesToReadRightNow = framesToRead; + ma_uint32 framesToReadRightNow = framesToRead; if (framesToReadRightNow > sizeof(tempBuffer)/sizeof(tempBuffer[0])/DEVICE_CHANNELS) { framesToReadRightNow = sizeof(tempBuffer)/sizeof(tempBuffer[0])/DEVICE_CHANNELS; } - mal_uint32 framesJustRead = (mal_uint32)mal_dsp_read(&audioBuffer->dsp, framesToReadRightNow, tempBuffer, audioBuffer->dsp.pUserData); + ma_uint32 framesJustRead = (ma_uint32)ma_pcm_converter_read(&audioBuffer->dsp, tempBuffer, framesToReadRightNow); if (framesJustRead > 0) { - float *framesOut = (float *)pFramesOut + (framesRead*device.channels); + float *framesOut = (float *)pFramesOut + (framesRead*device.playback.channels); float *framesIn = tempBuffer; MixAudioFrames(framesOut, framesIn, framesJustRead, audioBuffer->volume); @@ -357,18 +354,16 @@ static mal_uint32 OnSendAudioDataToDevice(mal_device *pDevice, mal_uint32 frameC } } - mal_mutex_unlock(&audioLock); - - return frameCount; // We always output the same number of frames that were originally requested. + ma_mutex_unlock(&audioLock); } // DSP read from audio buffer callback function -static mal_uint32 OnAudioBufferDSPRead(mal_dsp *pDSP, mal_uint32 frameCount, void *pFramesOut, void *pUserData) +static ma_uint32 OnAudioBufferDSPRead(ma_pcm_converter *pDSP, void *pFramesOut, ma_uint32 frameCount, void *pUserData) { AudioBuffer *audioBuffer = (AudioBuffer *)pUserData; - mal_uint32 subBufferSizeInFrames = audioBuffer->bufferSizeInFrames/2; - mal_uint32 currentSubBufferIndex = audioBuffer->frameCursorPos/subBufferSizeInFrames; + ma_uint32 subBufferSizeInFrames = (audioBuffer->bufferSizeInFrames > 1)? audioBuffer->bufferSizeInFrames/2 : audioBuffer->bufferSizeInFrames; + ma_uint32 currentSubBufferIndex = audioBuffer->frameCursorPos/subBufferSizeInFrames; if (currentSubBufferIndex > 1) { @@ -381,10 +376,10 @@ static mal_uint32 OnAudioBufferDSPRead(mal_dsp *pDSP, mal_uint32 frameCount, voi isSubBufferProcessed[0] = audioBuffer->isSubBufferProcessed[0]; isSubBufferProcessed[1] = audioBuffer->isSubBufferProcessed[1]; - mal_uint32 frameSizeInBytes = mal_get_bytes_per_sample(audioBuffer->dsp.formatConverterIn.config.formatIn)*audioBuffer->dsp.formatConverterIn.config.channels; + ma_uint32 frameSizeInBytes = ma_get_bytes_per_sample(audioBuffer->dsp.formatConverterIn.config.formatIn)*audioBuffer->dsp.formatConverterIn.config.channels; // Fill out every frame until we find a buffer that's marked as processed. Then fill the remainder with 0. - mal_uint32 framesRead = 0; + ma_uint32 framesRead = 0; for (;;) { // We break from this loop differently depending on the buffer's usage. For static buffers, we simply fill as much data as we can. For @@ -398,21 +393,21 @@ static mal_uint32 OnAudioBufferDSPRead(mal_dsp *pDSP, mal_uint32 frameCount, voi if (isSubBufferProcessed[currentSubBufferIndex]) break; } - mal_uint32 totalFramesRemaining = (frameCount - framesRead); + ma_uint32 totalFramesRemaining = (frameCount - framesRead); if (totalFramesRemaining == 0) break; - mal_uint32 framesRemainingInOutputBuffer; + ma_uint32 framesRemainingInOutputBuffer; if (audioBuffer->usage == AUDIO_BUFFER_USAGE_STATIC) { framesRemainingInOutputBuffer = audioBuffer->bufferSizeInFrames - audioBuffer->frameCursorPos; } else { - mal_uint32 firstFrameIndexOfThisSubBuffer = subBufferSizeInFrames * currentSubBufferIndex; + ma_uint32 firstFrameIndexOfThisSubBuffer = subBufferSizeInFrames * currentSubBufferIndex; framesRemainingInOutputBuffer = subBufferSizeInFrames - (audioBuffer->frameCursorPos - firstFrameIndexOfThisSubBuffer); } - mal_uint32 framesToRead = totalFramesRemaining; + ma_uint32 framesToRead = totalFramesRemaining; if (framesToRead > framesRemainingInOutputBuffer) framesToRead = framesRemainingInOutputBuffer; memcpy((unsigned char *)pFramesOut + (framesRead*frameSizeInBytes), audioBuffer->buffer + (audioBuffer->frameCursorPos*frameSizeInBytes), framesToRead*frameSizeInBytes); @@ -437,7 +432,7 @@ static mal_uint32 OnAudioBufferDSPRead(mal_dsp *pDSP, mal_uint32 frameCount, voi } // Zero-fill excess. - mal_uint32 totalFramesRemaining = (frameCount - framesRead); + ma_uint32 totalFramesRemaining = (frameCount - framesRead); if (totalFramesRemaining > 0) { memset((unsigned char *)pFramesOut + (framesRead*frameSizeInBytes), 0, totalFramesRemaining*frameSizeInBytes); @@ -453,16 +448,16 @@ static mal_uint32 OnAudioBufferDSPRead(mal_dsp *pDSP, mal_uint32 frameCount, voi // This is the main mixing function. Mixing is pretty simple in this project - it's just an accumulation. // NOTE: framesOut is both an input and an output. It will be initially filled with zeros outside of this function. -static void MixAudioFrames(float *framesOut, const float *framesIn, mal_uint32 frameCount, float localVolume) +static void MixAudioFrames(float *framesOut, const float *framesIn, ma_uint32 frameCount, float localVolume) { - for (mal_uint32 iFrame = 0; iFrame < frameCount; ++iFrame) + for (ma_uint32 iFrame = 0; iFrame < frameCount; ++iFrame) { - for (mal_uint32 iChannel = 0; iChannel < device.channels; ++iChannel) + for (ma_uint32 iChannel = 0; iChannel < device.playback.channels; ++iChannel) { - float *frameOut = framesOut + (iFrame*device.channels); - const float *frameIn = framesIn + (iFrame*device.channels); + float *frameOut = framesOut + (iFrame*device.playback.channels); + const float *frameIn = framesIn + (iFrame*device.playback.channels); - frameOut[iChannel] += frameIn[iChannel]*masterVolume*localVolume; + frameOut[iChannel] += (frameIn[iChannel]*masterVolume*localVolume); } } } @@ -474,54 +469,64 @@ static void MixAudioFrames(float *framesOut, const float *framesIn, mal_uint32 f void InitAudioDevice(void) { // Context. - mal_context_config contextConfig = mal_context_config_init(OnLog); - mal_result result = mal_context_init(NULL, 0, &contextConfig, &context); - if (result != MAL_SUCCESS) + ma_context_config contextConfig = ma_context_config_init(); + contextConfig.logCallback = OnLog; + ma_result result = ma_context_init(NULL, 0, &contextConfig, &context); + if (result != MA_SUCCESS) { TraceLog(LOG_ERROR, "Failed to initialize audio context"); return; } // Device. Using the default device. Format is floating point because it simplifies mixing. - mal_device_config deviceConfig = mal_device_config_init(DEVICE_FORMAT, DEVICE_CHANNELS, DEVICE_SAMPLE_RATE, NULL, OnSendAudioDataToDevice); - - result = mal_device_init(&context, mal_device_type_playback, NULL, &deviceConfig, NULL, &device); - if (result != MAL_SUCCESS) + ma_device_config config = ma_device_config_init(ma_device_type_playback); + config.playback.pDeviceID = NULL; // NULL for the default playback device. + config.playback.format = DEVICE_FORMAT; + config.playback.channels = DEVICE_CHANNELS; + config.capture.pDeviceID = NULL; // NULL for the default capture device. + config.capture.format = ma_format_s16; + config.capture.channels = 1; + config.sampleRate = DEVICE_SAMPLE_RATE; + config.dataCallback = OnSendAudioDataToDevice; + config.pUserData = NULL; + + result = ma_device_init(&context, &config, &device); + if (result != MA_SUCCESS) { TraceLog(LOG_ERROR, "Failed to initialize audio playback device"); - mal_context_uninit(&context); + ma_context_uninit(&context); return; } // Keep the device running the whole time. May want to consider doing something a bit smarter and only have the device running // while there's at least one sound being played. - result = mal_device_start(&device); - if (result != MAL_SUCCESS) + result = ma_device_start(&device); + if (result != MA_SUCCESS) { TraceLog(LOG_ERROR, "Failed to start audio playback device"); - mal_device_uninit(&device); - mal_context_uninit(&context); + ma_device_uninit(&device); + ma_context_uninit(&context); return; } // Mixing happens on a seperate thread which means we need to synchronize. I'm using a mutex here to make things simple, but may // want to look at something a bit smarter later on to keep everything real-time, if that's necessary. - if (mal_mutex_init(&context, &audioLock) != MAL_SUCCESS) + if (ma_mutex_init(&context, &audioLock) != MA_SUCCESS) { TraceLog(LOG_ERROR, "Failed to create mutex for audio mixing"); - mal_device_uninit(&device); - mal_context_uninit(&context); + ma_device_uninit(&device); + ma_context_uninit(&context); return; } - TraceLog(LOG_INFO, "Audio device initialized successfully: %s", device.name); - TraceLog(LOG_INFO, "Audio backend: mini_al / %s", mal_get_backend_name(context.backend)); - TraceLog(LOG_INFO, "Audio format: %s -> %s", mal_get_format_name(device.format), mal_get_format_name(device.internalFormat)); - TraceLog(LOG_INFO, "Audio channels: %d -> %d", device.channels, device.internalChannels); - TraceLog(LOG_INFO, "Audio sample rate: %d -> %d", device.sampleRate, device.internalSampleRate); - TraceLog(LOG_INFO, "Audio buffer size: %d", device.bufferSizeInFrames); + TraceLog(LOG_INFO, "Audio device initialized successfully"); + TraceLog(LOG_INFO, "Audio backend: miniaudio / %s", ma_get_backend_name(context.backend)); + TraceLog(LOG_INFO, "Audio format: %s -> %s", ma_get_format_name(device.playback.format), ma_get_format_name(device.playback.internalFormat)); + TraceLog(LOG_INFO, "Audio channels: %d -> %d", device.playback.channels, device.playback.internalChannels); + TraceLog(LOG_INFO, "Audio sample rate: %d -> %d", device.sampleRate, device.playback.internalSampleRate); + TraceLog(LOG_INFO, "Audio buffer size: %d", device.playback.internalBufferSizeInFrames); - isAudioInitialized = MAL_TRUE; + isAudioInitialized = MA_TRUE; } // Close the audio device for all contexts @@ -533,9 +538,9 @@ void CloseAudioDevice(void) return; } - mal_mutex_uninit(&audioLock); - mal_device_uninit(&device); - mal_context_uninit(&context); + ma_mutex_uninit(&audioLock); + ma_device_uninit(&device); + ma_context_uninit(&context); TraceLog(LOG_INFO, "Audio device closed successfully"); } @@ -560,9 +565,9 @@ void SetMasterVolume(float volume) //---------------------------------------------------------------------------------- // Create a new audio buffer. Initially filled with silence -AudioBuffer *CreateAudioBuffer(mal_format format, mal_uint32 channels, mal_uint32 sampleRate, mal_uint32 bufferSizeInFrames, AudioBufferUsage usage) +AudioBuffer *CreateAudioBuffer(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, ma_uint32 bufferSizeInFrames, AudioBufferUsage usage) { - AudioBuffer *audioBuffer = (AudioBuffer *)calloc(sizeof(*audioBuffer) + (bufferSizeInFrames*channels*mal_get_bytes_per_sample(format)), 1); + AudioBuffer *audioBuffer = (AudioBuffer *)RL_CALLOC(sizeof(*audioBuffer) + (bufferSizeInFrames*channels*ma_get_bytes_per_sample(format)), 1); if (audioBuffer == NULL) { TraceLog(LOG_ERROR, "CreateAudioBuffer() : Failed to allocate memory for audio buffer"); @@ -570,7 +575,7 @@ AudioBuffer *CreateAudioBuffer(mal_format format, mal_uint32 channels, mal_uint3 } // We run audio data through a format converter. - mal_dsp_config dspConfig; + ma_pcm_converter_config dspConfig; memset(&dspConfig, 0, sizeof(dspConfig)); dspConfig.formatIn = format; dspConfig.formatOut = DEVICE_FORMAT; @@ -580,20 +585,21 @@ AudioBuffer *CreateAudioBuffer(mal_format format, mal_uint32 channels, mal_uint3 dspConfig.sampleRateOut = DEVICE_SAMPLE_RATE; dspConfig.onRead = OnAudioBufferDSPRead; dspConfig.pUserData = audioBuffer; - dspConfig.allowDynamicSampleRate = MAL_TRUE; // <-- Required for pitch shifting. - mal_result resultMAL = mal_dsp_init(&dspConfig, &audioBuffer->dsp); - if (resultMAL != MAL_SUCCESS) + dspConfig.allowDynamicSampleRate = MA_TRUE; // <-- Required for pitch shifting. + ma_result result = ma_pcm_converter_init(&dspConfig, &audioBuffer->dsp); + + if (result != MA_SUCCESS) { TraceLog(LOG_ERROR, "CreateAudioBuffer() : Failed to create data conversion pipeline"); - free(audioBuffer); + RL_FREE(audioBuffer); return NULL; } - audioBuffer->volume = 1; - audioBuffer->pitch = 1; - audioBuffer->playing = 0; - audioBuffer->paused = 0; - audioBuffer->looping = 0; + audioBuffer->volume = 1.0f; + audioBuffer->pitch = 1.0f; + audioBuffer->playing = false; + audioBuffer->paused = false; + audioBuffer->looping = false; audioBuffer->usage = usage; audioBuffer->bufferSizeInFrames = bufferSizeInFrames; audioBuffer->frameCursorPos = 0; @@ -617,7 +623,7 @@ void DeleteAudioBuffer(AudioBuffer *audioBuffer) } UntrackAudioBuffer(audioBuffer); - free(audioBuffer); + RL_FREE(audioBuffer); } // Check if an audio buffer is playing @@ -696,7 +702,7 @@ void SetAudioBufferVolume(AudioBuffer *audioBuffer, float volume) { if (audioBuffer == NULL) { - TraceLog(LOG_ERROR, "SetAudioBufferVolume() : No audio buffer"); + TraceLog(LOG_WARNING, "SetAudioBufferVolume() : No audio buffer"); return; } @@ -708,22 +714,24 @@ void SetAudioBufferPitch(AudioBuffer *audioBuffer, float pitch) { if (audioBuffer == NULL) { - TraceLog(LOG_ERROR, "SetAudioBufferPitch() : No audio buffer"); + TraceLog(LOG_WARNING, "SetAudioBufferPitch() : No audio buffer"); return; } - audioBuffer->pitch = pitch; + float pitchMul = pitch/audioBuffer->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. - mal_uint32 newOutputSampleRate = (mal_uint32)((((float)audioBuffer->dsp.src.config.sampleRateOut / (float)audioBuffer->dsp.src.config.sampleRateIn) / pitch) * audioBuffer->dsp.src.config.sampleRateIn); - mal_dsp_set_output_sample_rate(&audioBuffer->dsp, newOutputSampleRate); + ma_uint32 newOutputSampleRate = (ma_uint32)((float)audioBuffer->dsp.src.config.sampleRateOut / pitchMul); + audioBuffer->pitch *= (float)audioBuffer->dsp.src.config.sampleRateOut / newOutputSampleRate; + + ma_pcm_converter_set_output_sample_rate(&audioBuffer->dsp, newOutputSampleRate); } // Track audio buffer to linked list next position void TrackAudioBuffer(AudioBuffer *audioBuffer) { - mal_mutex_lock(&audioLock); + ma_mutex_lock(&audioLock); { if (firstAudioBuffer == NULL) firstAudioBuffer = audioBuffer; @@ -736,13 +744,13 @@ void TrackAudioBuffer(AudioBuffer *audioBuffer) lastAudioBuffer = audioBuffer; } - mal_mutex_unlock(&audioLock); + ma_mutex_unlock(&audioLock); } // Untrack audio buffer from linked list void UntrackAudioBuffer(AudioBuffer *audioBuffer) { - mal_mutex_lock(&audioLock); + ma_mutex_lock(&audioLock); { if (audioBuffer->prev == NULL) firstAudioBuffer = audioBuffer->next; @@ -755,7 +763,7 @@ void UntrackAudioBuffer(AudioBuffer *audioBuffer) audioBuffer->next = NULL; } - mal_mutex_unlock(&audioLock); + ma_mutex_unlock(&audioLock); } //---------------------------------------------------------------------------------- @@ -826,7 +834,7 @@ Sound LoadSoundFromWave(Wave wave) if (wave.data != NULL) { - // When using mini_al we need to do our own mixing. To simplify this we need convert the format of each sound to be consistent with + // When using miniaudio we need to do our own mixing. To simplify this we need convert the format of each sound to be consistent with // the format used to open the playback device. We can do this two ways: // // 1) Convert the whole sound in one go at load time (here). @@ -834,16 +842,16 @@ Sound LoadSoundFromWave(Wave wave) // // I have decided on the first option because it offloads work required for the format conversion to the to the loading stage. // The downside to this is that it uses more memory if the original sound is u8 or s16. - mal_format formatIn = ((wave.sampleSize == 8) ? mal_format_u8 : ((wave.sampleSize == 16) ? mal_format_s16 : mal_format_f32)); - mal_uint32 frameCountIn = wave.sampleCount/wave.channels; + ma_format formatIn = ((wave.sampleSize == 8)? ma_format_u8 : ((wave.sampleSize == 16)? ma_format_s16 : ma_format_f32)); + ma_uint32 frameCountIn = wave.sampleCount/wave.channels; - mal_uint32 frameCount = (mal_uint32)mal_convert_frames(NULL, DEVICE_FORMAT, DEVICE_CHANNELS, DEVICE_SAMPLE_RATE, NULL, formatIn, wave.channels, wave.sampleRate, frameCountIn); + ma_uint32 frameCount = (ma_uint32)ma_convert_frames(NULL, DEVICE_FORMAT, DEVICE_CHANNELS, DEVICE_SAMPLE_RATE, NULL, formatIn, wave.channels, wave.sampleRate, frameCountIn); if (frameCount == 0) TraceLog(LOG_WARNING, "LoadSoundFromWave() : Failed to get frame count for format conversion"); AudioBuffer* audioBuffer = CreateAudioBuffer(DEVICE_FORMAT, DEVICE_CHANNELS, DEVICE_SAMPLE_RATE, frameCount, AUDIO_BUFFER_USAGE_STATIC); if (audioBuffer == NULL) TraceLog(LOG_WARNING, "LoadSoundFromWave() : Failed to create audio buffer"); - frameCount = (mal_uint32)mal_convert_frames(audioBuffer->buffer, audioBuffer->dsp.formatConverterIn.config.formatIn, audioBuffer->dsp.formatConverterIn.config.channels, audioBuffer->dsp.src.config.sampleRateIn, wave.data, formatIn, wave.channels, wave.sampleRate, frameCountIn); + frameCount = (ma_uint32)ma_convert_frames(audioBuffer->buffer, audioBuffer->dsp.formatConverterIn.config.formatIn, audioBuffer->dsp.formatConverterIn.config.channels, audioBuffer->dsp.src.config.sampleRateIn, wave.data, formatIn, wave.channels, wave.sampleRate, frameCountIn); if (frameCount == 0) TraceLog(LOG_WARNING, "LoadSoundFromWave() : Format conversion failed"); sound.audioBuffer = audioBuffer; @@ -855,7 +863,7 @@ Sound LoadSoundFromWave(Wave wave) // Unload wave data void UnloadWave(Wave wave) { - if (wave.data != NULL) free(wave.data); + if (wave.data != NULL) RL_FREE(wave.data); TraceLog(LOG_INFO, "Unloaded wave data from RAM"); } @@ -883,7 +891,7 @@ void UpdateSound(Sound sound, const void *data, int samplesCount) 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*mal_get_bytes_per_sample(audioBuffer->dsp.formatConverterIn.config.formatIn)); + memcpy(audioBuffer->buffer, data, samplesCount*audioBuffer->dsp.formatConverterIn.config.channels*ma_get_bytes_per_sample(audioBuffer->dsp.formatConverterIn.config.formatIn)); } // Export wave data to file @@ -946,7 +954,7 @@ void ExportWaveAsCode(Wave wave, const char *fileName) // Write byte data as hexadecimal text fprintf(txtFile, "static unsigned char %s_DATA[%i] = { ", varFileName, dataSize); - for (int i = 0; i < dataSize - 1; i++) fprintf(txtFile, ((i%BYTES_TEXT_PER_LINE == 0) ? "0x%x,\n" : "0x%x, "), ((unsigned char *)wave.data)[i]); + for (int i = 0; i < dataSize - 1; i++) fprintf(txtFile, ((i%BYTES_TEXT_PER_LINE == 0)? "0x%x,\n" : "0x%x, "), ((unsigned char *)wave.data)[i]); fprintf(txtFile, "0x%x };\n", ((unsigned char *)wave.data)[dataSize - 1]); fclose(txtFile); @@ -997,21 +1005,21 @@ void SetSoundPitch(Sound sound, float pitch) // Convert wave data to desired format void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels) { - mal_format formatIn = ((wave->sampleSize == 8) ? mal_format_u8 : ((wave->sampleSize == 16) ? mal_format_s16 : mal_format_f32)); - mal_format formatOut = (( sampleSize == 8) ? mal_format_u8 : (( sampleSize == 16) ? mal_format_s16 : mal_format_f32)); + ma_format formatIn = ((wave->sampleSize == 8)? ma_format_u8 : ((wave->sampleSize == 16)? ma_format_s16 : ma_format_f32)); + ma_format formatOut = (( sampleSize == 8)? ma_format_u8 : (( sampleSize == 16)? ma_format_s16 : ma_format_f32)); - mal_uint32 frameCountIn = wave->sampleCount; // Is wave->sampleCount actually the frame count? That terminology needs to change, if so. + ma_uint32 frameCountIn = wave->sampleCount; // Is wave->sampleCount actually the frame count? That terminology needs to change, if so. - mal_uint32 frameCount = (mal_uint32)mal_convert_frames(NULL, formatOut, channels, sampleRate, NULL, formatIn, wave->channels, wave->sampleRate, frameCountIn); + ma_uint32 frameCount = (ma_uint32)ma_convert_frames(NULL, formatOut, channels, sampleRate, NULL, formatIn, wave->channels, wave->sampleRate, frameCountIn); if (frameCount == 0) { TraceLog(LOG_ERROR, "WaveFormat() : Failed to get frame count for format conversion."); return; } - void *data = malloc(frameCount*channels*(sampleSize/8)); + void *data = RL_MALLOC(frameCount*channels*(sampleSize/8)); - frameCount = (mal_uint32)mal_convert_frames(data, formatOut, channels, sampleRate, wave->data, formatIn, wave->channels, wave->sampleRate, frameCountIn); + frameCount = (ma_uint32)ma_convert_frames(data, formatOut, channels, sampleRate, wave->data, formatIn, wave->channels, wave->sampleRate, frameCountIn); if (frameCount == 0) { TraceLog(LOG_ERROR, "WaveFormat() : Format conversion failed."); @@ -1022,7 +1030,7 @@ void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels) wave->sampleSize = sampleSize; wave->sampleRate = sampleRate; wave->channels = channels; - free(wave->data); + RL_FREE(wave->data); wave->data = data; } @@ -1031,7 +1039,7 @@ Wave WaveCopy(Wave wave) { Wave newWave = { 0 }; - newWave.data = malloc(wave.sampleCount*wave.sampleSize/8*wave.channels); + newWave.data = RL_MALLOC(wave.sampleCount*wave.sampleSize/8*wave.channels); if (newWave.data != NULL) { @@ -1056,11 +1064,11 @@ void WaveCrop(Wave *wave, int initSample, int finalSample) { int sampleCount = finalSample - initSample; - void *data = malloc(sampleCount*wave->sampleSize/8*wave->channels); + void *data = RL_MALLOC(sampleCount*wave->sampleSize/8*wave->channels); memcpy(data, (unsigned char *)wave->data + (initSample*wave->channels*wave->sampleSize/8), sampleCount*wave->channels*wave->sampleSize/8); - free(wave->data); + RL_FREE(wave->data); wave->data = data; } else TraceLog(LOG_WARNING, "Wave crop range out of bounds"); @@ -1070,7 +1078,7 @@ void WaveCrop(Wave *wave, int initSample, int finalSample) // NOTE: Returned sample values are normalized to range [-1..1] float *GetWaveData(Wave wave) { - float *samples = (float *)malloc(wave.sampleCount*wave.channels*sizeof(float)); + float *samples = (float *)RL_MALLOC(wave.sampleCount*wave.channels*sizeof(float)); for (unsigned int i = 0; i < wave.sampleCount; i++) { @@ -1092,7 +1100,7 @@ float *GetWaveData(Wave wave) // Load music stream from file Music LoadMusicStream(const char *fileName) { - Music music = (MusicData *)malloc(sizeof(MusicData)); + Music music = (MusicData *)RL_MALLOC(sizeof(MusicData)); bool musicLoaded = true; #if defined(SUPPORT_FILEFORMAT_OGG) @@ -1232,7 +1240,7 @@ Music LoadMusicStream(const char *fileName) else if (music->ctxType == MUSIC_MODULE_MOD) jar_mod_unload(&music->ctxMod); #endif - free(music); + RL_FREE(music); music = NULL; TraceLog(LOG_WARNING, "[%s] Music file could not be opened", fileName); @@ -1245,7 +1253,7 @@ Music LoadMusicStream(const char *fileName) void UnloadMusicStream(Music music) { if (music == NULL) return; - + CloseAudioStream(music->stream); #if defined(SUPPORT_FILEFORMAT_OGG) @@ -1266,7 +1274,7 @@ void UnloadMusicStream(Music music) else if (music->ctxType == MUSIC_MODULE_MOD) jar_mod_unload(&music->ctxMod); #endif - free(music); + RL_FREE(music); } // Start music playing (open stream) @@ -1286,7 +1294,7 @@ void PlayMusicStream(Music music) // // NOTE: In case window is minimized, music stream is stopped, // // just make sure to play again on window restore // if (IsMusicPlaying(music)) PlayMusicStream(music); - mal_uint32 frameCursorPos = audioBuffer->frameCursorPos; + ma_uint32 frameCursorPos = audioBuffer->frameCursorPos; PlayAudioStream(music->stream); // <-- This resets the cursor position. @@ -1311,7 +1319,7 @@ void ResumeMusicStream(Music music) void StopMusicStream(Music music) { if (music == NULL) return; - + StopAudioStream(music->stream); // Restart music context @@ -1327,7 +1335,7 @@ void StopMusicStream(Music music) case MUSIC_AUDIO_MP3: drmp3_seek_to_pcm_frame(&music->ctxMp3, 0); break; #endif #if defined(SUPPORT_FILEFORMAT_XM) - case MUSIC_MODULE_XM: /* TODO: Restart XM context */ break; + case MUSIC_MODULE_XM: jar_xm_reset(music->ctxXm); break; #endif #if defined(SUPPORT_FILEFORMAT_MOD) case MUSIC_MODULE_MOD: jar_mod_seek_start(&music->ctxMod); break; @@ -1343,13 +1351,13 @@ void StopMusicStream(Music music) void UpdateMusicStream(Music music) { if (music == NULL) return; - + bool streamEnding = false; unsigned int subBufferSizeInFrames = ((AudioBuffer *)music->stream.audioBuffer)->bufferSizeInFrames/2; // NOTE: Using dynamic allocation because it could require more than 16KB - void *pcm = calloc(subBufferSizeInFrames*music->stream.channels*music->stream.sampleSize/8, 1); + 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 @@ -1393,21 +1401,21 @@ void UpdateMusicStream(Music music) } break; #endif #if defined(SUPPORT_FILEFORMAT_MOD) - case MUSIC_MODULE_MOD: + case MUSIC_MODULE_MOD: { // NOTE: 3rd parameter (nbsample) specify the number of stereo 16bits samples you want, so sampleCount/2 - jar_mod_fillbuffer(&music->ctxMod, (short *)pcm, samplesCount/2, 0); + jar_mod_fillbuffer(&music->ctxMod, (short *)pcm, samplesCount/2, 0); } break; #endif default: break; } - + UpdateAudioStream(music->stream, pcm, samplesCount); if ((music->ctxType == MUSIC_MODULE_XM) || (music->ctxType == MUSIC_MODULE_MOD)) { - if (samplesCount > 1) music->samplesLeft -= samplesCount/2; - else music->samplesLeft -= samplesCount; + if (samplesCount > 1) music->samplesLeft -= samplesCount/2; + else music->samplesLeft -= samplesCount; } else music->samplesLeft -= samplesCount; @@ -1419,7 +1427,7 @@ void UpdateMusicStream(Music music) } // Free allocated pcm data - free(pcm); + RL_FREE(pcm); // Reset audio stream for looping if (streamEnding) @@ -1475,7 +1483,7 @@ void SetMusicLoopCount(Music music, int count) float GetMusicTimeLength(Music music) { float totalSeconds = 0.0f; - + if (music != NULL) totalSeconds = (float)music->totalSamples/(music->stream.sampleRate*music->stream.channels); return totalSeconds; @@ -1511,10 +1519,10 @@ AudioStream InitAudioStream(unsigned int sampleRate, unsigned int sampleSize, un stream.channels = 1; // Fallback to mono channel } - mal_format formatIn = ((stream.sampleSize == 8) ? mal_format_u8 : ((stream.sampleSize == 16) ? mal_format_s16 : mal_format_f32)); + ma_format formatIn = ((stream.sampleSize == 8)? ma_format_u8 : ((stream.sampleSize == 16)? ma_format_s16 : ma_format_f32)); // The size of a streaming buffer must be at least double the size of a period. - unsigned int periodSize = device.bufferSizeInFrames/device.periods; + unsigned int periodSize = device.playback.internalBufferSizeInFrames/device.playback.internalPeriods; unsigned int subBufferSize = AUDIO_BUFFER_SIZE; if (subBufferSize < periodSize) subBufferSize = periodSize; @@ -1528,7 +1536,7 @@ AudioStream InitAudioStream(unsigned int sampleRate, unsigned int sampleSize, un audioBuffer->looping = true; // Always loop for streaming buffers. stream.audioBuffer = audioBuffer; - TraceLog(LOG_INFO, "[AUD ID %i] Audio stream loaded successfully (%i Hz, %i bit, %s)", stream.source, stream.sampleRate, stream.sampleSize, (stream.channels == 1) ? "Mono" : "Stereo"); + TraceLog(LOG_INFO, "[AUD ID %i] Audio stream loaded successfully (%i Hz, %i bit, %s)", stream.source, stream.sampleRate, stream.sampleSize, (stream.channels == 1)? "Mono" : "Stereo"); return stream; } @@ -1555,7 +1563,7 @@ void UpdateAudioStream(AudioStream stream, const void *data, int samplesCount) if (audioBuffer->isSubBufferProcessed[0] || audioBuffer->isSubBufferProcessed[1]) { - mal_uint32 subBufferToUpdate; + ma_uint32 subBufferToUpdate; if (audioBuffer->isSubBufferProcessed[0] && audioBuffer->isSubBufferProcessed[1]) { @@ -1566,24 +1574,24 @@ void UpdateAudioStream(AudioStream stream, const void *data, int samplesCount) else { // Just update whichever sub-buffer is processed. - subBufferToUpdate = (audioBuffer->isSubBufferProcessed[0]) ? 0 : 1; + subBufferToUpdate = (audioBuffer->isSubBufferProcessed[0])? 0 : 1; } - mal_uint32 subBufferSizeInFrames = audioBuffer->bufferSizeInFrames/2; + ma_uint32 subBufferSizeInFrames = audioBuffer->bufferSizeInFrames/2; unsigned char *subBuffer = audioBuffer->buffer + ((subBufferSizeInFrames*stream.channels*(stream.sampleSize/8))*subBufferToUpdate); // 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 >= (mal_uint32)samplesCount/stream.channels) + if (subBufferSizeInFrames >= (ma_uint32)samplesCount/stream.channels) { - mal_uint32 framesToWrite = subBufferSizeInFrames; + ma_uint32 framesToWrite = subBufferSizeInFrames; - if (framesToWrite > ((mal_uint32)samplesCount/stream.channels)) framesToWrite = (mal_uint32)samplesCount/stream.channels; + if (framesToWrite > ((ma_uint32)samplesCount/stream.channels)) framesToWrite = (ma_uint32)samplesCount/stream.channels; - mal_uint32 bytesToWrite = framesToWrite*stream.channels*(stream.sampleSize/8); + ma_uint32 bytesToWrite = framesToWrite*stream.channels*(stream.sampleSize/8); memcpy(subBuffer, data, bytesToWrite); // Any leftover frames should be filled with zeros. - mal_uint32 leftoverFrameCount = subBufferSizeInFrames - framesToWrite; + ma_uint32 leftoverFrameCount = subBufferSizeInFrames - framesToWrite; if (leftoverFrameCount > 0) { @@ -1742,7 +1750,7 @@ static Wave LoadWAV(const char *fileName) else { // Allocate memory for data - wave.data = malloc(wavData.subChunkSize); + wave.data = RL_MALLOC(wavData.subChunkSize); // Read in the sound data into the soundData variable fread(wave.data, wavData.subChunkSize, 1, wavFile); @@ -1769,7 +1777,7 @@ static Wave LoadWAV(const char *fileName) // NOTE: subChunkSize comes in bytes, we need to translate it to number of samples wave.sampleCount = (wavData.subChunkSize/(wave.sampleSize/8))/wave.channels; - TraceLog(LOG_INFO, "[%s] WAV file loaded successfully (%i Hz, %i bit, %s)", fileName, wave.sampleRate, wave.sampleSize, (wave.channels == 1) ? "Mono" : "Stereo"); + TraceLog(LOG_INFO, "[%s] WAV file loaded successfully (%i Hz, %i bit, %s)", fileName, wave.sampleRate, wave.sampleSize, (wave.channels == 1)? "Mono" : "Stereo"); } } } @@ -1883,14 +1891,14 @@ static Wave LoadOGG(const char *fileName) float totalSeconds = stb_vorbis_stream_length_in_seconds(oggFile); if (totalSeconds > 10) TraceLog(LOG_WARNING, "[%s] Ogg audio length is larger than 10 seconds (%f), that's a big file in memory, consider music streaming", fileName, totalSeconds); - wave.data = (short *)malloc(wave.sampleCount*wave.channels*sizeof(short)); + wave.data = (short *)RL_MALLOC(wave.sampleCount*wave.channels*sizeof(short)); // NOTE: Returns the number of samples to process (be careful! we ask for number of shorts!) int numSamplesOgg = stb_vorbis_get_samples_short_interleaved(oggFile, info.channels, (short *)wave.data, wave.sampleCount*wave.channels); TraceLog(LOG_DEBUG, "[%s] Samples obtained: %i", fileName, numSamplesOgg); - TraceLog(LOG_INFO, "[%s] OGG file loaded successfully (%i Hz, %i bit, %s)", fileName, wave.sampleRate, wave.sampleSize, (wave.channels == 1) ? "Mono" : "Stereo"); + TraceLog(LOG_INFO, "[%s] OGG file loaded successfully (%i Hz, %i bit, %s)", fileName, wave.sampleRate, wave.sampleSize, (wave.channels == 1)? "Mono" : "Stereo"); stb_vorbis_close(oggFile); } @@ -1917,7 +1925,7 @@ static Wave LoadFLAC(const char *fileName) if (wave.channels > 2) TraceLog(LOG_WARNING, "[%s] FLAC channels number (%i) not supported", fileName, wave.channels); if (wave.data == NULL) TraceLog(LOG_WARNING, "[%s] FLAC data could not be loaded", fileName); - else TraceLog(LOG_INFO, "[%s] FLAC file loaded successfully (%i Hz, %i bit, %s)", fileName, wave.sampleRate, wave.sampleSize, (wave.channels == 1) ? "Mono" : "Stereo"); + else TraceLog(LOG_INFO, "[%s] FLAC file loaded successfully (%i Hz, %i bit, %s)", fileName, wave.sampleRate, wave.sampleSize, (wave.channels == 1)? "Mono" : "Stereo"); return wave; } @@ -1944,7 +1952,7 @@ static Wave LoadMP3(const char *fileName) if (wave.channels > 2) TraceLog(LOG_WARNING, "[%s] MP3 channels number (%i) not supported", fileName, wave.channels); if (wave.data == NULL) TraceLog(LOG_WARNING, "[%s] MP3 data could not be loaded", fileName); - else TraceLog(LOG_INFO, "[%s] MP3 file loaded successfully (%i Hz, %i bit, %s)", fileName, wave.sampleRate, wave.sampleSize, (wave.channels == 1) ? "Mono" : "Stereo"); + else TraceLog(LOG_INFO, "[%s] MP3 file loaded successfully (%i Hz, %i bit, %s)", fileName, wave.sampleRate, wave.sampleSize, (wave.channels == 1)? "Mono" : "Stereo"); return wave; } |
