From a2a3d3aeb60dd117b02fc8c7c85ec428175a5f83 Mon Sep 17 00:00:00 2001 From: Joshua Reisenauer Date: Sun, 1 May 2016 18:53:40 -0700 Subject: [PATCH 1/7] new silence generator --- src/audio.c | 74 ++++++++++++++++++++++++++++++++++++---------------- src/audio.h | 7 ++--- src/raylib.h | 7 ++--- 3 files changed, 60 insertions(+), 28 deletions(-) diff --git a/src/audio.c b/src/audio.c index 8a8ca4ef7..7100a6c1a 100644 --- a/src/audio.c +++ b/src/audio.c @@ -37,6 +37,7 @@ #include "AL/al.h" // OpenAL basic header #include "AL/alc.h" // OpenAL context header (like OpenGL, OpenAL requires a context to work) +#include "AL/alext.h" // extensions for other format types #include // Declares malloc() and free() for memory management #include // Required for strcmp() @@ -93,12 +94,10 @@ typedef struct Music { // Audio Context, used to create custom audio streams that are not bound to a sound file. There can be // no more than 4 concurrent audio contexts in use. This is due to each active context being tied to -// a dedicated mix channel. +// a dedicated mix channel. All audio is 32bit floating point in stereo. typedef struct AudioContext_t { unsigned short sampleRate; // default is 48000 - unsigned char bitsPerSample; // 16 is default unsigned char mixChannel; // 0-3 or mixA-mixD, each mix channel can receive up to one dedicated audio stream - unsigned char channels; // 1=mono, 2=stereo ALenum alFormat; // openAL format specifier ALuint alSource; // openAL source ALuint alBuffer[2]; // openAL sample buffer @@ -126,6 +125,9 @@ static void UnloadWave(Wave wave); // Unload wave data static bool BufferMusicStream(ALuint buffer); // Fill music buffers with data static void EmptyMusicStream(void); // Empty music buffers +// fill buffer with zeros +static void FillAlBufferWithSilence(AudioContext_t *ac, ALuint buffer); + #if defined(AUDIO_STANDALONE) const char *GetExtension(const char *fileName); // Get the extension for a filename void TraceLog(int msgType, const char *text, ...); // Outputs a trace log message (INFO, ERROR, WARNING) @@ -197,8 +199,9 @@ bool IsAudioDeviceReady(void) // Audio contexts are for outputing custom audio waveforms, This will shut down any other sound sources currently playing // The mixChannel is what mix channel you want to operate on, 0-3 are the ones available. Each mix channel can only be used one at a time. -// exmple usage is InitAudioContext(48000, 16, 0, 2); // stereo, mixchannel 1, 16bit, 48khz -AudioContext InitAudioContext(unsigned short sampleRate, unsigned char bitsPerSample, unsigned char mixChannel, unsigned char channels) +// exmple usage is InitAudioContext(48000, 0); // mixchannel 1, 48khz +// all samples are floating point stereo by default +AudioContext InitAudioContext(unsigned short sampleRate, unsigned char mixChannel) { if(mixChannel > MAX_AUDIO_CONTEXTS) return NULL; if(!IsAudioDeviceReady()) InitAudioDevice(); @@ -207,22 +210,11 @@ AudioContext InitAudioContext(unsigned short sampleRate, unsigned char bitsPerSa if(!mixChannelsActive_g[mixChannel]){ AudioContext_t *ac = malloc(sizeof(AudioContext_t)); ac->sampleRate = sampleRate; - ac->bitsPerSample = bitsPerSample; ac->mixChannel = mixChannel; - ac->channels = channels; mixChannelsActive_g[mixChannel] = ac; // setup openAL format - if (channels == 1) - { - if (bitsPerSample == 8 ) ac->alFormat = AL_FORMAT_MONO8; - else if (bitsPerSample == 16) ac->alFormat = AL_FORMAT_MONO16; - } - else if (channels == 2) - { - if (bitsPerSample == 8 ) ac->alFormat = AL_FORMAT_STEREO8; - else if (bitsPerSample == 16) ac->alFormat = AL_FORMAT_STEREO16; - } + ac->alFormat = AL_FORMAT_STEREO_FLOAT32; // Create an audio source alGenSources(1, &ac->alSource); @@ -232,7 +224,14 @@ AudioContext InitAudioContext(unsigned short sampleRate, unsigned char bitsPerSa alSource3f(ac->alSource, AL_VELOCITY, 0, 0, 0); // Create Buffer - alGenBuffers(2, &ac->alBuffer); + alGenBuffers(2, ac->alBuffer); + + //fill buffers + FillAlBufferWithSilence(ac, ac->alBuffer[0]); + FillAlBufferWithSilence(ac, ac->alBuffer[1]); + alSourceQueueBuffers(ac->alSource, 2, ac->alBuffer); + alSourcei(ac->alSource, AL_LOOPING, AL_FALSE); // this could cause errors + alSourcePlay(ac->alSource); return ac; @@ -245,8 +244,20 @@ void CloseAudioContext(AudioContext ctx) { AudioContext_t *context = (AudioContext_t*)ctx; if(context){ + alSourceStop(context->alSource); + + //flush out all queued buffers + ALuint buffer = 0; + int queued = 0; + alGetSourcei(context->alSource, AL_BUFFERS_QUEUED, &queued); + while (queued > 0) + { + alSourceUnqueueBuffers(context->alSource, 1, &buffer); + queued--; + } + alDeleteSources(1, &context->alSource); - alDeleteBuffers(2, &context->alBuffer); + alDeleteBuffers(2, context->alBuffer); mixChannelsActive_g[context->mixChannel] = NULL; free(context); ctx = NULL; @@ -254,15 +265,34 @@ void CloseAudioContext(AudioContext ctx) } // Pushes more audio data into context mix channel, if none are ever pushed then zeros are fed in -void UpdateAudioContext(AudioContext ctx, void *data, unsigned short *dataLength) +// Call "UpdateAudioContext(ctx, NULL, 0)" every game tick if you want to pause the audio +void UpdateAudioContext(AudioContext ctx, float *data, unsigned short dataLength) { AudioContext_t *context = (AudioContext_t*)ctx; - if(!musicEnabled && context && mixChannelsActive_g[context->mixChannel] == context) + if (context && mixChannelsActive_g[context->mixChannel] == context) { - ; + ALint processed = 0; + ALuint buffer = 0; + alGetSourcei(context->alSource, AL_BUFFERS_PROCESSED, &processed); // Get the number of already processed buffers (if any) + + if (!data || !dataLength)// play silence + while (processed > 0) + { + alSourceUnqueueBuffers(context->alSource, 1, &buffer); + FillAlBufferWithSilence(context, buffer); + alSourceQueueBuffers(context->alSource, 1, &buffer); + processed--; + } } } +// fill buffer with zeros +static void FillAlBufferWithSilence(AudioContext_t *ac, ALuint buffer) +{ + float pcm[MUSIC_BUFFER_SIZE] = {0.f}; + alBufferData(buffer, ac->alFormat, pcm, MUSIC_BUFFER_SIZE*sizeof(float), ac->sampleRate); +} + //---------------------------------------------------------------------------------- diff --git a/src/audio.h b/src/audio.h index 9c681044b..9037a8438 100644 --- a/src/audio.h +++ b/src/audio.h @@ -84,10 +84,11 @@ bool IsAudioDeviceReady(void); // True if call // Audio contexts are for outputing custom audio waveforms, This will shut down any other sound sources currently playing // The mixChannel is what mix channel you want to operate on, 0-3 are the ones available. Each mix channel can only be used one at a time. -// exmple usage is InitAudioContext(48000, 16, 0, 2); // stereo, mixchannel 1, 16bit, 48khz -AudioContext InitAudioContext(unsigned short sampleRate, unsigned char bitsPerSample, unsigned char mixChannel, unsigned char channels); +// exmple usage is InitAudioContext(48000, 0); // mixchannel 1, 48khz +// all samples are floating point stereo by default +AudioContext InitAudioContext(unsigned short sampleRate, unsigned char mixChannel); void CloseAudioContext(AudioContext ctx); // Frees audio context -void UpdateAudioContext(AudioContext ctx, void *data, unsigned short *dataLength); // Pushes more audio data into context mix channel, if none are ever pushed then zeros are fed in +void UpdateAudioContext(AudioContext ctx, float *data, unsigned short dataLength); // Pushes more audio data into context mix channel, if NULL is passed to data then zeros are played Sound LoadSound(char *fileName); // Load sound to memory Sound LoadSoundFromWave(Wave wave); // Load sound to memory from wave data diff --git a/src/raylib.h b/src/raylib.h index 8390d1761..f4ea875e7 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -872,10 +872,11 @@ bool IsAudioDeviceReady(void); // True if call // Audio contexts are for outputing custom audio waveforms, This will shut down any other sound sources currently playing // The mixChannel is what mix channel you want to operate on, 0-3 are the ones available. Each mix channel can only be used one at a time. -// exmple usage is InitAudioContext(48000, 16, 0, 2); // stereo, mixchannel 1, 16bit, 48khz -AudioContext InitAudioContext(unsigned short sampleRate, unsigned char bitsPerSample, unsigned char mixChannel, unsigned char channels); +// exmple usage is InitAudioContext(48000, 0); // mixchannel 1, 48khz +// all samples are floating point stereo by default +AudioContext InitAudioContext(unsigned short sampleRate, unsigned char mixChannel); void CloseAudioContext(AudioContext ctx); // Frees audio context -void UpdateAudioContext(AudioContext ctx, void *data, unsigned short *dataLength); // Pushes more audio data into context mix channel, if none are ever pushed then zeros are fed in +void UpdateAudioContext(AudioContext ctx, float *data, unsigned short dataLength); // Pushes more audio data into context mix channel, if NULL is passed to data then zeros are played Sound LoadSound(char *fileName); // Load sound to memory Sound LoadSoundFromWave(Wave wave); // Load sound to memory from wave data From 790bc7280685d714ddce3e1ee0afa11cee0c5e06 Mon Sep 17 00:00:00 2001 From: Joshua Reisenauer Date: Sun, 1 May 2016 23:07:02 -0700 Subject: [PATCH 2/7] bool return for failed update --- src/audio.c | 9 +++++++-- src/audio.h | 2 +- src/raylib.h | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/audio.c b/src/audio.c index 7100a6c1a..7b42b089c 100644 --- a/src/audio.c +++ b/src/audio.c @@ -256,6 +256,7 @@ void CloseAudioContext(AudioContext ctx) queued--; } + //delete source and buffers alDeleteSources(1, &context->alSource); alDeleteBuffers(2, context->alBuffer); mixChannelsActive_g[context->mixChannel] = NULL; @@ -266,7 +267,8 @@ void CloseAudioContext(AudioContext ctx) // Pushes more audio data into context mix channel, if none are ever pushed then zeros are fed in // Call "UpdateAudioContext(ctx, NULL, 0)" every game tick if you want to pause the audio -void UpdateAudioContext(AudioContext ctx, float *data, unsigned short dataLength) +// Returns true if data was pushed onto queue, otherwise if queue is full then no data is added and false is returned +bool UpdateAudioContext(AudioContext ctx, float *data, unsigned short dataLength) { AudioContext_t *context = (AudioContext_t*)ctx; if (context && mixChannelsActive_g[context->mixChannel] == context) @@ -274,7 +276,9 @@ void UpdateAudioContext(AudioContext ctx, float *data, unsigned short dataLength ALint processed = 0; ALuint buffer = 0; alGetSourcei(context->alSource, AL_BUFFERS_PROCESSED, &processed); // Get the number of already processed buffers (if any) - + + if(!processed) return false;//nothing to process, queue is still full + if (!data || !dataLength)// play silence while (processed > 0) { @@ -283,6 +287,7 @@ void UpdateAudioContext(AudioContext ctx, float *data, unsigned short dataLength alSourceQueueBuffers(context->alSource, 1, &buffer); processed--; } + return true; } } diff --git a/src/audio.h b/src/audio.h index 9037a8438..4a198c59d 100644 --- a/src/audio.h +++ b/src/audio.h @@ -88,7 +88,7 @@ bool IsAudioDeviceReady(void); // True if call // all samples are floating point stereo by default AudioContext InitAudioContext(unsigned short sampleRate, unsigned char mixChannel); void CloseAudioContext(AudioContext ctx); // Frees audio context -void UpdateAudioContext(AudioContext ctx, float *data, unsigned short dataLength); // Pushes more audio data into context mix channel, if NULL is passed to data then zeros are played +bool UpdateAudioContext(AudioContext ctx, float *data, unsigned short dataLength); // Pushes more audio data into context mix channel, if NULL is passed to data then zeros are played Sound LoadSound(char *fileName); // Load sound to memory Sound LoadSoundFromWave(Wave wave); // Load sound to memory from wave data diff --git a/src/raylib.h b/src/raylib.h index ade581d39..9c5a8258d 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -874,7 +874,7 @@ bool IsAudioDeviceReady(void); // True if call // all samples are floating point stereo by default AudioContext InitAudioContext(unsigned short sampleRate, unsigned char mixChannel); void CloseAudioContext(AudioContext ctx); // Frees audio context -void UpdateAudioContext(AudioContext ctx, float *data, unsigned short dataLength); // Pushes more audio data into context mix channel, if NULL is passed to data then zeros are played +bool UpdateAudioContext(AudioContext ctx, float *data, unsigned short dataLength); // Pushes more audio data into context mix channel, if NULL is passed to data then zeros are played Sound LoadSound(char *fileName); // Load sound to memory Sound LoadSoundFromWave(Wave wave); // Load sound to memory from wave data From 9ef0240e99e7e6a626fdb8fee4f8a81eea21f3e2 Mon Sep 17 00:00:00 2001 From: Joshua Reisenauer Date: Mon, 2 May 2016 01:24:24 -0700 Subject: [PATCH 3/7] resamples added Ease of use considered in api and channels are more convenient as unsigned char type. --- src/audio.c | 49 +++++++++++++++++++++++++++++++++++++++++++------ src/audio.h | 6 +++--- src/raylib.h | 6 +++--- 3 files changed, 49 insertions(+), 12 deletions(-) diff --git a/src/audio.c b/src/audio.c index 7b42b089c..d935b6c74 100644 --- a/src/audio.c +++ b/src/audio.c @@ -97,6 +97,7 @@ typedef struct Music { // a dedicated mix channel. All audio is 32bit floating point in stereo. typedef struct AudioContext_t { unsigned short sampleRate; // default is 48000 + unsigned char channels; // 1=mono,2=stereo unsigned char mixChannel; // 0-3 or mixA-mixD, each mix channel can receive up to one dedicated audio stream ALenum alFormat; // openAL format specifier ALuint alSource; // openAL source @@ -125,8 +126,9 @@ static void UnloadWave(Wave wave); // Unload wave data static bool BufferMusicStream(ALuint buffer); // Fill music buffers with data static void EmptyMusicStream(void); // Empty music buffers -// fill buffer with zeros -static void FillAlBufferWithSilence(AudioContext_t *ac, ALuint buffer); +static void FillAlBufferWithSilence(AudioContext_t *ac, ALuint buffer);// fill buffer with zeros +static void ResampleShortToFloat(short *shorts, float *floats, unsigned short len); // pass two arrays of the same legnth in +static void ResampleByteToFloat(char *chars, float *floats, unsigned short len); // pass two arrays of same length in #if defined(AUDIO_STANDALONE) const char *GetExtension(const char *fileName); // Get the extension for a filename @@ -199,9 +201,9 @@ bool IsAudioDeviceReady(void) // Audio contexts are for outputing custom audio waveforms, This will shut down any other sound sources currently playing // The mixChannel is what mix channel you want to operate on, 0-3 are the ones available. Each mix channel can only be used one at a time. -// exmple usage is InitAudioContext(48000, 0); // mixchannel 1, 48khz -// all samples are floating point stereo by default -AudioContext InitAudioContext(unsigned short sampleRate, unsigned char mixChannel) +// exmple usage is InitAudioContext(48000, 0, 2); // mixchannel 1, 48khz, stereo +// all samples are floating point by default +AudioContext InitAudioContext(unsigned short sampleRate, unsigned char mixChannel, unsigned char channels) { if(mixChannel > MAX_AUDIO_CONTEXTS) return NULL; if(!IsAudioDeviceReady()) InitAudioDevice(); @@ -210,11 +212,15 @@ AudioContext InitAudioContext(unsigned short sampleRate, unsigned char mixChanne if(!mixChannelsActive_g[mixChannel]){ AudioContext_t *ac = malloc(sizeof(AudioContext_t)); ac->sampleRate = sampleRate; + ac->channels = channels; ac->mixChannel = mixChannel; mixChannelsActive_g[mixChannel] = ac; // setup openAL format - ac->alFormat = AL_FORMAT_STEREO_FLOAT32; + if(channels == 1) + ac->alFormat = AL_FORMAT_MONO_FLOAT32; + else + ac->alFormat = AL_FORMAT_STEREO_FLOAT32; // Create an audio source alGenSources(1, &ac->alSource); @@ -289,6 +295,7 @@ bool UpdateAudioContext(AudioContext ctx, float *data, unsigned short dataLength } return true; } + return false; } // fill buffer with zeros @@ -298,6 +305,36 @@ static void FillAlBufferWithSilence(AudioContext_t *ac, ALuint buffer) alBufferData(buffer, ac->alFormat, pcm, MUSIC_BUFFER_SIZE*sizeof(float), ac->sampleRate); } +// example usage: +// short sh[3] = {1,2,3};float fl[3]; +// ResampleShortToFloat(sh,fl,3); +static void ResampleShortToFloat(short *shorts, float *floats, unsigned short len) +{ + int x; + for(x=0;x Date: Mon, 2 May 2016 14:37:00 -0700 Subject: [PATCH 4/7] number remaining buffer transfer for updateAudioContext updateAudioContext is almost done --- src/audio.c | 39 +++++++++++++++++++++++++++++++-------- src/audio.h | 2 +- src/raylib.h | 2 +- 3 files changed, 33 insertions(+), 10 deletions(-) diff --git a/src/audio.c b/src/audio.c index d935b6c74..ff4f2858e 100644 --- a/src/audio.c +++ b/src/audio.c @@ -273,17 +273,20 @@ void CloseAudioContext(AudioContext ctx) // Pushes more audio data into context mix channel, if none are ever pushed then zeros are fed in // Call "UpdateAudioContext(ctx, NULL, 0)" every game tick if you want to pause the audio -// Returns true if data was pushed onto queue, otherwise if queue is full then no data is added and false is returned -bool UpdateAudioContext(AudioContext ctx, float *data, unsigned short dataLength) +// Returns number of floats that where processed +unsigned short UpdateAudioContext(AudioContext ctx, float *data, unsigned short dataLength) { + unsigned short numberProcessed = 0; + unsigned short numberRemaining = dataLength; AudioContext_t *context = (AudioContext_t*)ctx; + if (context && mixChannelsActive_g[context->mixChannel] == context) { ALint processed = 0; ALuint buffer = 0; alGetSourcei(context->alSource, AL_BUFFERS_PROCESSED, &processed); // Get the number of already processed buffers (if any) - if(!processed) return false;//nothing to process, queue is still full + if(!processed) return 0;//nothing to process, queue is still full if (!data || !dataLength)// play silence while (processed > 0) @@ -292,17 +295,37 @@ bool UpdateAudioContext(AudioContext ctx, float *data, unsigned short dataLength FillAlBufferWithSilence(context, buffer); alSourceQueueBuffers(context->alSource, 1, &buffer); processed--; + numberProcessed+=MUSIC_BUFFER_SIZE; + } + if(numberRemaining)// buffer data stream in increments of MUSIC_BUFFER_SIZE + while (processed > 0) + { + alSourceUnqueueBuffers(context->alSource, 1, &buffer); + if(numberRemaining >= MUSIC_BUFFER_SIZE) + { + float pcm[MUSIC_BUFFER_SIZE]; + memcpy(pcm, &data[numberProcessed], MUSIC_BUFFER_SIZE); + alBufferData(buffer, context->alFormat, pcm, MUSIC_BUFFER_SIZE*sizeof(float), context->sampleRate); + alSourceQueueBuffers(context->alSource, 1, &buffer); + numberProcessed+=MUSIC_BUFFER_SIZE; + numberRemaining-=MUSIC_BUFFER_SIZE; + } + else // less than MUSIC_BUFFER_SIZE number of samples left to buffer, the remaining data is padded with zeros + { + float pcm[MUSIC_BUFFER_SIZE] = {0.f}; // pad with zeros + } + + processed--; } - return true; } - return false; + return numberProcessed; } // fill buffer with zeros -static void FillAlBufferWithSilence(AudioContext_t *ac, ALuint buffer) +static void FillAlBufferWithSilence(AudioContext_t *context, ALuint buffer) { float pcm[MUSIC_BUFFER_SIZE] = {0.f}; - alBufferData(buffer, ac->alFormat, pcm, MUSIC_BUFFER_SIZE*sizeof(float), ac->sampleRate); + alBufferData(buffer, context->alFormat, pcm, MUSIC_BUFFER_SIZE*sizeof(float), context->sampleRate); } // example usage: @@ -322,7 +345,7 @@ static void ResampleShortToFloat(short *shorts, float *floats, unsigned short le // example usage: // char ch[3] = {1,2,3};float fl[3]; -// ResampleShortToFloat(ch,fl,3); +// ResampleByteToFloat(ch,fl,3); static void ResampleByteToFloat(char *chars, float *floats, unsigned short len) { int x; diff --git a/src/audio.h b/src/audio.h index d723ef1b0..2b36b3f04 100644 --- a/src/audio.h +++ b/src/audio.h @@ -88,7 +88,7 @@ bool IsAudioDeviceReady(void); // True if call // all samples are floating point by default AudioContext InitAudioContext(unsigned short sampleRate, unsigned char mixChannel, unsigned char channels); void CloseAudioContext(AudioContext ctx); // Frees audio context -bool UpdateAudioContext(AudioContext ctx, float *data, unsigned short dataLength); // Pushes more audio data into context mix channel, if NULL is passed to data then zeros are played +unsigned short UpdateAudioContext(AudioContext ctx, float *data, unsigned short dataLength); // Pushes more audio data into context mix channel, if NULL is passed to data then zeros are played Sound LoadSound(char *fileName); // Load sound to memory Sound LoadSoundFromWave(Wave wave); // Load sound to memory from wave data diff --git a/src/raylib.h b/src/raylib.h index 3fa20116b..5c727b615 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -874,7 +874,7 @@ bool IsAudioDeviceReady(void); // True if call // all samples are floating point by default AudioContext InitAudioContext(unsigned short sampleRate, unsigned char mixChannel, unsigned char channels); void CloseAudioContext(AudioContext ctx); // Frees audio context -bool UpdateAudioContext(AudioContext ctx, float *data, unsigned short dataLength); // Pushes more audio data into context mix channel, if NULL is passed to data then zeros are played +unsigned short UpdateAudioContext(AudioContext ctx, float *data, unsigned short dataLength); // Pushes more audio data into context mix channel, if NULL is passed to data then zeros are played Sound LoadSound(char *fileName); // Load sound to memory Sound LoadSoundFromWave(Wave wave); // Load sound to memory from wave data From 9d09ada33b26704a7f5d285d2f0d115e41df41bf Mon Sep 17 00:00:00 2001 From: Joshua Reisenauer Date: Mon, 2 May 2016 21:59:55 -0700 Subject: [PATCH 5/7] new boolean floatingPoint option Now floating point is either on or off. This simplifies the use of 16bit vs float. --- src/audio.c | 132 ++++++++++++++++++++++++++++++++------------------- src/audio.h | 7 ++- src/raylib.h | 7 ++- 3 files changed, 88 insertions(+), 58 deletions(-) diff --git a/src/audio.c b/src/audio.c index ff4f2858e..dc0637960 100644 --- a/src/audio.c +++ b/src/audio.c @@ -59,15 +59,17 @@ //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- -#define MUSIC_STREAM_BUFFERS 2 -#define MAX_AUDIO_CONTEXTS 4 +#define MAX_STREAM_BUFFERS 2 +#define MAX_AUDIO_CONTEXTS 4 // Number of open AL sources #if defined(PLATFORM_RPI) || defined(PLATFORM_ANDROID) // NOTE: On RPI and Android should be lower to avoid frame-stalls - #define MUSIC_BUFFER_SIZE 4096*2 // PCM data buffer (short) - 16Kb (RPI) + #define MUSIC_BUFFER_SIZE_SHORT 4096*2 // PCM data buffer (short) - 16Kb (RPI) + #define MUSIC_BUFFER_SIZE_FLOAT 4096 // PCM data buffer (float) - 16Kb (RPI) #else // NOTE: On HTML5 (emscripten) this is allocated on heap, by default it's only 16MB!...just take care... - #define MUSIC_BUFFER_SIZE 4096*8 // PCM data buffer (short) - 64Kb + #define MUSIC_BUFFER_SIZE_SHORT 4096*8 // PCM data buffer (short) - 64Kb + #define MUSIC_BUFFER_SIZE_FLOAT 4096*4 // PCM data buffer (float) - 64Kb #endif //---------------------------------------------------------------------------------- @@ -80,7 +82,7 @@ typedef struct Music { stb_vorbis *stream; jar_xm_context_t *chipctx; // Stores jar_xm context - ALuint buffers[MUSIC_STREAM_BUFFERS]; + ALuint buffers[MAX_STREAM_BUFFERS]; ALuint source; ALenum format; @@ -96,12 +98,13 @@ typedef struct Music { // no more than 4 concurrent audio contexts in use. This is due to each active context being tied to // a dedicated mix channel. All audio is 32bit floating point in stereo. typedef struct AudioContext_t { - unsigned short sampleRate; // default is 48000 - unsigned char channels; // 1=mono,2=stereo - unsigned char mixChannel; // 0-3 or mixA-mixD, each mix channel can receive up to one dedicated audio stream - ALenum alFormat; // openAL format specifier - ALuint alSource; // openAL source - ALuint alBuffer[2]; // openAL sample buffer + unsigned short sampleRate; // default is 48000 + unsigned char channels; // 1=mono,2=stereo + unsigned char mixChannel; // 0-3 or mixA-mixD, each mix channel can receive up to one dedicated audio stream + bool floatingPoint; // if false then the short datatype is used instead + ALenum alFormat; // openAL format specifier + ALuint alSource; // openAL source + ALuint alBuffer[MAX_STREAM_BUFFERS]; // openAL sample buffer } AudioContext_t; #if defined(AUDIO_STANDALONE) @@ -126,7 +129,7 @@ static void UnloadWave(Wave wave); // Unload wave data static bool BufferMusicStream(ALuint buffer); // Fill music buffers with data static void EmptyMusicStream(void); // Empty music buffers -static void FillAlBufferWithSilence(AudioContext_t *ac, ALuint buffer);// fill buffer with zeros +static unsigned short FillAlBufferWithSilence(AudioContext_t *context, ALuint buffer);// fill buffer with zeros, returns number processed static void ResampleShortToFloat(short *shorts, float *floats, unsigned short len); // pass two arrays of the same legnth in static void ResampleByteToFloat(char *chars, float *floats, unsigned short len); // pass two arrays of same length in @@ -201,11 +204,10 @@ bool IsAudioDeviceReady(void) // Audio contexts are for outputing custom audio waveforms, This will shut down any other sound sources currently playing // The mixChannel is what mix channel you want to operate on, 0-3 are the ones available. Each mix channel can only be used one at a time. -// exmple usage is InitAudioContext(48000, 0, 2); // mixchannel 1, 48khz, stereo -// all samples are floating point by default -AudioContext InitAudioContext(unsigned short sampleRate, unsigned char mixChannel, unsigned char channels) +// exmple usage is InitAudioContext(48000, 0, 2, true); // mixchannel 1, 48khz, stereo, floating point +AudioContext InitAudioContext(unsigned short sampleRate, unsigned char mixChannel, unsigned char channels, bool floatingPoint) { - if(mixChannel > MAX_AUDIO_CONTEXTS) return NULL; + if(mixChannel >= MAX_AUDIO_CONTEXTS) return NULL; if(!IsAudioDeviceReady()) InitAudioDevice(); else StopMusicStream(); @@ -214,13 +216,24 @@ AudioContext InitAudioContext(unsigned short sampleRate, unsigned char mixChanne ac->sampleRate = sampleRate; ac->channels = channels; ac->mixChannel = mixChannel; + ac->floatingPoint = floatingPoint; mixChannelsActive_g[mixChannel] = ac; // setup openAL format if(channels == 1) - ac->alFormat = AL_FORMAT_MONO_FLOAT32; - else - ac->alFormat = AL_FORMAT_STEREO_FLOAT32; + { + if(floatingPoint) + ac->alFormat = AL_FORMAT_MONO_FLOAT32; + else + ac->alFormat = AL_FORMAT_MONO16; + } + else if(channels == 2) + { + if(floatingPoint) + ac->alFormat = AL_FORMAT_STEREO_FLOAT32; + else + ac->alFormat = AL_FORMAT_STEREO16; + } // Create an audio source alGenSources(1, &ac->alSource); @@ -230,16 +243,17 @@ AudioContext InitAudioContext(unsigned short sampleRate, unsigned char mixChanne alSource3f(ac->alSource, AL_VELOCITY, 0, 0, 0); // Create Buffer - alGenBuffers(2, ac->alBuffer); + alGenBuffers(MAX_STREAM_BUFFERS, ac->alBuffer); //fill buffers - FillAlBufferWithSilence(ac, ac->alBuffer[0]); - FillAlBufferWithSilence(ac, ac->alBuffer[1]); - alSourceQueueBuffers(ac->alSource, 2, ac->alBuffer); + int x; + for(x=0;xalBuffer[x]); + + alSourceQueueBuffers(ac->alSource, MAX_STREAM_BUFFERS, ac->alBuffer); alSourcei(ac->alSource, AL_LOOPING, AL_FALSE); // this could cause errors alSourcePlay(ac->alSource); - return ac; } return NULL; @@ -264,20 +278,22 @@ void CloseAudioContext(AudioContext ctx) //delete source and buffers alDeleteSources(1, &context->alSource); - alDeleteBuffers(2, context->alBuffer); + alDeleteBuffers(MAX_STREAM_BUFFERS, context->alBuffer); mixChannelsActive_g[context->mixChannel] = NULL; free(context); ctx = NULL; } } -// Pushes more audio data into context mix channel, if none are ever pushed then zeros are fed in -// Call "UpdateAudioContext(ctx, NULL, 0)" every game tick if you want to pause the audio -// Returns number of floats that where processed -unsigned short UpdateAudioContext(AudioContext ctx, float *data, unsigned short dataLength) +// Pushes more audio data into context mix channel, if none are ever pushed then zeros are fed in. +// Call "UpdateAudioContext(ctx, NULL, 0)" every game tick if you want to pause the audio. +// @Returns number of samples that where processed. +// All data streams should be of a length that is evenly divisible by MUSIC_BUFFER_SIZE, +// otherwise the remaining data will not be pushed. +unsigned short UpdateAudioContext(AudioContext ctx, void *data, unsigned short numberElements) { unsigned short numberProcessed = 0; - unsigned short numberRemaining = dataLength; + unsigned short numberRemaining = numberElements; AudioContext_t *context = (AudioContext_t*)ctx; if (context && mixChannelsActive_g[context->mixChannel] == context) @@ -288,44 +304,60 @@ unsigned short UpdateAudioContext(AudioContext ctx, float *data, unsigned short if(!processed) return 0;//nothing to process, queue is still full - if (!data || !dataLength)// play silence + if (!data || !numberElements)// play silence + { while (processed > 0) { alSourceUnqueueBuffers(context->alSource, 1, &buffer); - FillAlBufferWithSilence(context, buffer); + numberProcessed += FillAlBufferWithSilence(context, buffer); alSourceQueueBuffers(context->alSource, 1, &buffer); processed--; - numberProcessed+=MUSIC_BUFFER_SIZE; } + } if(numberRemaining)// buffer data stream in increments of MUSIC_BUFFER_SIZE + { while (processed > 0) { - alSourceUnqueueBuffers(context->alSource, 1, &buffer); - if(numberRemaining >= MUSIC_BUFFER_SIZE) + if(context->floatingPoint && numberRemaining >= MUSIC_BUFFER_SIZE_FLOAT) // process float buffers { - float pcm[MUSIC_BUFFER_SIZE]; - memcpy(pcm, &data[numberProcessed], MUSIC_BUFFER_SIZE); - alBufferData(buffer, context->alFormat, pcm, MUSIC_BUFFER_SIZE*sizeof(float), context->sampleRate); + float *ptr = (float*)data; + alSourceUnqueueBuffers(context->alSource, 1, &buffer); + alBufferData(buffer, context->alFormat, &ptr[numberProcessed], MUSIC_BUFFER_SIZE_FLOAT*sizeof(float), context->sampleRate); alSourceQueueBuffers(context->alSource, 1, &buffer); - numberProcessed+=MUSIC_BUFFER_SIZE; - numberRemaining-=MUSIC_BUFFER_SIZE; + numberProcessed+=MUSIC_BUFFER_SIZE_FLOAT; + numberRemaining-=MUSIC_BUFFER_SIZE_FLOAT; } - else // less than MUSIC_BUFFER_SIZE number of samples left to buffer, the remaining data is padded with zeros + else if(!context->floatingPoint && numberRemaining >= MUSIC_BUFFER_SIZE_SHORT) // process short buffers { - float pcm[MUSIC_BUFFER_SIZE] = {0.f}; // pad with zeros + short *ptr = (short*)data; + alSourceUnqueueBuffers(context->alSource, 1, &buffer); + alBufferData(buffer, context->alFormat, &ptr[numberProcessed], MUSIC_BUFFER_SIZE_SHORT*sizeof(short), context->sampleRate); + alSourceQueueBuffers(context->alSource, 1, &buffer); + numberProcessed+=MUSIC_BUFFER_SIZE_SHORT; + numberRemaining-=MUSIC_BUFFER_SIZE_SHORT; } processed--; } + } } return numberProcessed; } -// fill buffer with zeros -static void FillAlBufferWithSilence(AudioContext_t *context, ALuint buffer) +// fill buffer with zeros, returns number processed +static unsigned short FillAlBufferWithSilence(AudioContext_t *context, ALuint buffer) { - float pcm[MUSIC_BUFFER_SIZE] = {0.f}; - alBufferData(buffer, context->alFormat, pcm, MUSIC_BUFFER_SIZE*sizeof(float), context->sampleRate); + if(context->floatingPoint){ + float pcm[MUSIC_BUFFER_SIZE_FLOAT] = {0.f}; + alBufferData(buffer, context->alFormat, pcm, MUSIC_BUFFER_SIZE_FLOAT*sizeof(float), context->sampleRate); + return MUSIC_BUFFER_SIZE_FLOAT; + } + else + { + short pcm[MUSIC_BUFFER_SIZE_SHORT] = {0}; + alBufferData(buffer, context->alFormat, pcm, MUSIC_BUFFER_SIZE_SHORT*sizeof(short), context->sampleRate); + return MUSIC_BUFFER_SIZE_SHORT; + } } // example usage: @@ -920,7 +952,7 @@ float GetMusicTimePlayed(void) // Fill music buffers with new data from music stream static bool BufferMusicStream(ALuint buffer) { - short pcm[MUSIC_BUFFER_SIZE]; + short pcm[MUSIC_BUFFER_SIZE_SHORT]; int size = 0; // Total size of data steamed (in bytes) int streamedBytes = 0; // samples of data obtained, channels are not included in calculation @@ -930,15 +962,15 @@ static bool BufferMusicStream(ALuint buffer) { if (currentMusic.chipTune) // There is no end of stream for xmfiles, once the end is reached zeros are generated for non looped chiptunes. { - int readlen = MUSIC_BUFFER_SIZE / 2; + int readlen = MUSIC_BUFFER_SIZE_SHORT / 2; jar_xm_generate_samples_16bit(currentMusic.chipctx, pcm, readlen); // reads 2*readlen shorts and moves them to buffer+size memory location size += readlen * currentMusic.channels; // Not sure if this is what it needs } else { - while (size < MUSIC_BUFFER_SIZE) + while (size < MUSIC_BUFFER_SIZE_SHORT) { - streamedBytes = stb_vorbis_get_samples_short_interleaved(currentMusic.stream, currentMusic.channels, pcm + size, MUSIC_BUFFER_SIZE - size); + streamedBytes = stb_vorbis_get_samples_short_interleaved(currentMusic.stream, currentMusic.channels, pcm + size, MUSIC_BUFFER_SIZE_SHORT - size); if (streamedBytes > 0) size += (streamedBytes*currentMusic.channels); else break; } diff --git a/src/audio.h b/src/audio.h index 2b36b3f04..9d6fa5d09 100644 --- a/src/audio.h +++ b/src/audio.h @@ -84,11 +84,10 @@ bool IsAudioDeviceReady(void); // True if call // Audio contexts are for outputing custom audio waveforms, This will shut down any other sound sources currently playing // The mixChannel is what mix channel you want to operate on, 0-3 are the ones available. Each mix channel can only be used one at a time. -// exmple usage is InitAudioContext(48000, 0, 2); // mixchannel 1, 48khz, stereo -// all samples are floating point by default -AudioContext InitAudioContext(unsigned short sampleRate, unsigned char mixChannel, unsigned char channels); +// exmple usage is InitAudioContext(48000, 0, 2, true); // mixchannel 1, 48khz, stereo, floating point +AudioContext InitAudioContext(unsigned short sampleRate, unsigned char mixChannel, unsigned char channels, bool floatingPoint); void CloseAudioContext(AudioContext ctx); // Frees audio context -unsigned short UpdateAudioContext(AudioContext ctx, float *data, unsigned short dataLength); // Pushes more audio data into context mix channel, if NULL is passed to data then zeros are played +unsigned short UpdateAudioContext(AudioContext ctx, void *data, unsigned short numberElements); // Pushes more audio data into context mix channel, if NULL is passed to data then zeros are played Sound LoadSound(char *fileName); // Load sound to memory Sound LoadSoundFromWave(Wave wave); // Load sound to memory from wave data diff --git a/src/raylib.h b/src/raylib.h index 5c727b615..c9ba5b384 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -870,11 +870,10 @@ bool IsAudioDeviceReady(void); // True if call // Audio contexts are for outputing custom audio waveforms, This will shut down any other sound sources currently playing // The mixChannel is what mix channel you want to operate on, 0-3 are the ones available. Each mix channel can only be used one at a time. -// exmple usage is InitAudioContext(48000, 0, 2); // mixchannel 1, 48khz, stereo -// all samples are floating point by default -AudioContext InitAudioContext(unsigned short sampleRate, unsigned char mixChannel, unsigned char channels); +// exmple usage is InitAudioContext(48000, 0, 2, true); // mixchannel 1, 48khz, stereo, floating point +AudioContext InitAudioContext(unsigned short sampleRate, unsigned char mixChannel, unsigned char channels, bool floatingPoint); void CloseAudioContext(AudioContext ctx); // Frees audio context -unsigned short UpdateAudioContext(AudioContext ctx, float *data, unsigned short dataLength); // Pushes more audio data into context mix channel, if NULL is passed to data then zeros are played +unsigned short UpdateAudioContext(AudioContext ctx, void *data, unsigned short numberElements); // Pushes more audio data into context mix channel, if NULL is passed to data then zeros are played Sound LoadSound(char *fileName); // Load sound to memory Sound LoadSoundFromWave(Wave wave); // Load sound to memory from wave data From d6feeb14ffc11e54a82f51dbbe899f720d6997e8 Mon Sep 17 00:00:00 2001 From: Joshua Reisenauer Date: Tue, 3 May 2016 02:52:45 -0700 Subject: [PATCH 6/7] pause on no data --- src/audio.c | 31 +++++++++++++++---------------- src/easings.h | 17 +++++++++++++++++ 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/src/audio.c b/src/audio.c index dc0637960..a46aa00ad 100644 --- a/src/audio.c +++ b/src/audio.c @@ -114,11 +114,10 @@ typedef enum { INFO = 0, ERROR, WARNING, DEBUG, OTHER } TraceLogType; //---------------------------------------------------------------------------------- // Global Variables Definition //---------------------------------------------------------------------------------- -static AudioContext_t* mixChannelsActive_g[MAX_AUDIO_CONTEXTS]; // What mix channels are currently active +static AudioContext_t* mixChannelsActive_g[MAX_AUDIO_CONTEXTS]; // What mix channels are currently active static bool musicEnabled = false; static Music currentMusic; // Current music loaded // NOTE: Only one music file playing at a time - //---------------------------------------------------------------------------------- // Module specific Functions Declaration //---------------------------------------------------------------------------------- @@ -286,34 +285,34 @@ void CloseAudioContext(AudioContext ctx) } // Pushes more audio data into context mix channel, if none are ever pushed then zeros are fed in. -// Call "UpdateAudioContext(ctx, NULL, 0)" every game tick if you want to pause the audio. +// Call "UpdateAudioContext(ctx, NULL, 0)" if you want to pause the audio. // @Returns number of samples that where processed. // All data streams should be of a length that is evenly divisible by MUSIC_BUFFER_SIZE, // otherwise the remaining data will not be pushed. unsigned short UpdateAudioContext(AudioContext ctx, void *data, unsigned short numberElements) { - unsigned short numberProcessed = 0; - unsigned short numberRemaining = numberElements; AudioContext_t *context = (AudioContext_t*)ctx; + if(context && context->channels == 2 && numberElements % 2 != 0) return 0; // when there is two channels there must be an even number of samples + + if (!data || !numberElements) alSourcePause(context->alSource); // pauses audio until data is given + else{ // restart audio otherwise + ALint state; + alGetSourcei(context->alSource, AL_SOURCE_STATE, &state); + if (state != AL_PLAYING) alSourcePlay(context->alSource); + } + if (context && mixChannelsActive_g[context->mixChannel] == context) { ALint processed = 0; ALuint buffer = 0; - alGetSourcei(context->alSource, AL_BUFFERS_PROCESSED, &processed); // Get the number of already processed buffers (if any) + unsigned short numberProcessed = 0; + unsigned short numberRemaining = numberElements; + + alGetSourcei(context->alSource, AL_BUFFERS_PROCESSED, &processed); // Get the number of already processed buffers (if any) if(!processed) return 0;//nothing to process, queue is still full - if (!data || !numberElements)// play silence - { - while (processed > 0) - { - alSourceUnqueueBuffers(context->alSource, 1, &buffer); - numberProcessed += FillAlBufferWithSilence(context, buffer); - alSourceQueueBuffers(context->alSource, 1, &buffer); - processed--; - } - } if(numberRemaining)// buffer data stream in increments of MUSIC_BUFFER_SIZE { while (processed > 0) diff --git a/src/easings.h b/src/easings.h index a198be4d8..e1e5465a6 100644 --- a/src/easings.h +++ b/src/easings.h @@ -7,6 +7,23 @@ * This header uses: * #define EASINGS_STATIC_INLINE // Inlines all functions code, so it runs faster. * // This requires lots of memory on system. +* How to use: +* The four inputs t,b,c,d are defined as follows: +* t = current time in milliseconds +* b = starting position in only one dimension [X || Y || Z] your choice +* c = the total change in value of b that needs to occur +* d = total time it should take to complete +* +* Example: +* float speed = 1.f; +* float currentTime = 0.f; +* float currentPos[2] = {0,0}; +* float newPos[2] = {1,1}; +* float tempPosition[2] = currentPos;//x,y positions +* while(currentPos[0] < newPos[0]) +* currentPos[0] = EaseSineIn(currentTime, tempPosition[0], tempPosition[0]-newPos[0], speed); +* currentPos[1] = EaseSineIn(currentTime, tempPosition[1], tempPosition[1]-newPos[0], speed); +* currentTime += diffTime(); * * A port of Robert Penner's easing equations to C (http://robertpenner.com/easing/) * From b7f8e97b0384ae37bff110a2ef42cc42cfa09228 Mon Sep 17 00:00:00 2001 From: Joshua Reisenauer Date: Tue, 10 May 2016 01:54:20 -0700 Subject: [PATCH 7/7] final fix for audiocontext system now it works --- src/audio.c | 74 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 51 insertions(+), 23 deletions(-) diff --git a/src/audio.c b/src/audio.c index 8f6431f6a..fbf53df66 100644 --- a/src/audio.c +++ b/src/audio.c @@ -102,6 +102,7 @@ typedef struct AudioContext_t { unsigned char channels; // 1=mono,2=stereo unsigned char mixChannel; // 0-3 or mixA-mixD, each mix channel can receive up to one dedicated audio stream bool floatingPoint; // if false then the short datatype is used instead + bool playing; ALenum alFormat; // openAL format specifier ALuint alSource; // openAL source ALuint alBuffer[MAX_STREAM_BUFFERS]; // openAL sample buffer @@ -211,7 +212,7 @@ AudioContext InitAudioContext(unsigned short sampleRate, unsigned char mixChanne else StopMusicStream(); if(!mixChannelsActive_g[mixChannel]){ - AudioContext_t *ac = malloc(sizeof(AudioContext_t)); + AudioContext_t *ac = (AudioContext_t*)malloc(sizeof(AudioContext_t)); ac->sampleRate = sampleRate; ac->channels = channels; ac->mixChannel = mixChannel; @@ -250,8 +251,8 @@ AudioContext InitAudioContext(unsigned short sampleRate, unsigned char mixChanne FillAlBufferWithSilence(ac, ac->alBuffer[x]); alSourceQueueBuffers(ac->alSource, MAX_STREAM_BUFFERS, ac->alBuffer); - alSourcei(ac->alSource, AL_LOOPING, AL_FALSE); // this could cause errors alSourcePlay(ac->alSource); + ac->playing = true; return ac; } @@ -264,6 +265,7 @@ void CloseAudioContext(AudioContext ctx) AudioContext_t *context = (AudioContext_t*)ctx; if(context){ alSourceStop(context->alSource); + context->playing = false; //flush out all queued buffers ALuint buffer = 0; @@ -287,22 +289,29 @@ void CloseAudioContext(AudioContext ctx) // Pushes more audio data into context mix channel, if none are ever pushed then zeros are fed in. // Call "UpdateAudioContext(ctx, NULL, 0)" if you want to pause the audio. // @Returns number of samples that where processed. -// All data streams should be of a length that is evenly divisible by MUSIC_BUFFER_SIZE, -// otherwise the remaining data will not be pushed. unsigned short UpdateAudioContext(AudioContext ctx, void *data, unsigned short numberElements) { AudioContext_t *context = (AudioContext_t*)ctx; - if(context && context->channels == 2 && numberElements % 2 != 0) return 0; // when there is two channels there must be an even number of samples + if(!context || (context->channels == 2 && numberElements % 2 != 0)) return 0; // when there is two channels there must be an even number of samples - if (!data || !numberElements) alSourcePause(context->alSource); // pauses audio until data is given - else{ // restart audio otherwise + if (!data || !numberElements) + { // pauses audio until data is given + alSourcePause(context->alSource); + context->playing = false; + return 0; + } + else + { // restart audio otherwise ALint state; alGetSourcei(context->alSource, AL_SOURCE_STATE, &state); - if (state != AL_PLAYING) alSourcePlay(context->alSource); + if (state != AL_PLAYING){ + alSourcePlay(context->alSource); + context->playing = true; + } } - if (context && mixChannelsActive_g[context->mixChannel] == context) + if (context && context->playing && mixChannelsActive_g[context->mixChannel] == context) { ALint processed = 0; ALuint buffer = 0; @@ -311,36 +320,55 @@ unsigned short UpdateAudioContext(AudioContext ctx, void *data, unsigned short n alGetSourcei(context->alSource, AL_BUFFERS_PROCESSED, &processed); // Get the number of already processed buffers (if any) - if(!processed) return 0;//nothing to process, queue is still full + if(!processed) return 0; // nothing to process, queue is still full - if(numberRemaining)// buffer data stream in increments of MUSIC_BUFFER_SIZE + + while (processed > 0) { - while (processed > 0) + if(context->floatingPoint) // process float buffers { - if(context->floatingPoint && numberRemaining >= MUSIC_BUFFER_SIZE_FLOAT) // process float buffers + float *ptr = (float*)data; + alSourceUnqueueBuffers(context->alSource, 1, &buffer); + if(numberRemaining >= MUSIC_BUFFER_SIZE_FLOAT) { - float *ptr = (float*)data; - alSourceUnqueueBuffers(context->alSource, 1, &buffer); alBufferData(buffer, context->alFormat, &ptr[numberProcessed], MUSIC_BUFFER_SIZE_FLOAT*sizeof(float), context->sampleRate); - alSourceQueueBuffers(context->alSource, 1, &buffer); numberProcessed+=MUSIC_BUFFER_SIZE_FLOAT; numberRemaining-=MUSIC_BUFFER_SIZE_FLOAT; } - else if(!context->floatingPoint && numberRemaining >= MUSIC_BUFFER_SIZE_SHORT) // process short buffers + else { - short *ptr = (short*)data; - alSourceUnqueueBuffers(context->alSource, 1, &buffer); - alBufferData(buffer, context->alFormat, &ptr[numberProcessed], MUSIC_BUFFER_SIZE_SHORT*sizeof(short), context->sampleRate); - alSourceQueueBuffers(context->alSource, 1, &buffer); + alBufferData(buffer, context->alFormat, &ptr[numberProcessed], numberRemaining*sizeof(float), context->sampleRate); + numberProcessed+=numberRemaining; + numberRemaining=0; + } + alSourceQueueBuffers(context->alSource, 1, &buffer); + processed--; + } + else if(!context->floatingPoint) // process short buffers + { + short *ptr = (short*)data; + alSourceUnqueueBuffers(context->alSource, 1, &buffer); + if(numberRemaining >= MUSIC_BUFFER_SIZE_SHORT) + { + alBufferData(buffer, context->alFormat, &ptr[numberProcessed], MUSIC_BUFFER_SIZE_FLOAT*sizeof(short), context->sampleRate); numberProcessed+=MUSIC_BUFFER_SIZE_SHORT; numberRemaining-=MUSIC_BUFFER_SIZE_SHORT; } - + else + { + alBufferData(buffer, context->alFormat, &ptr[numberProcessed], numberRemaining*sizeof(short), context->sampleRate); + numberProcessed+=numberRemaining; + numberRemaining=0; + } + alSourceQueueBuffers(context->alSource, 1, &buffer); processed--; } + else + break; } + return numberProcessed; } - return numberProcessed; + return 0; } // fill buffer with zeros, returns number processed