Improve AudioCallback
This commit is contained in:
parent
996f50393e
commit
615e28fa6d
|
|
@ -21,7 +21,7 @@ static float averageVolume[400] = { 0.0f }; // Average volume history
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Audio processing function
|
// Audio processing function
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
void ProcessAudio(void *buffer, unsigned int frames)
|
unsigned int ProcessAudio(void *buffer, unsigned int frames, void* userData)
|
||||||
{
|
{
|
||||||
float *samples = (float *)buffer; // Samples internally stored as <float>s
|
float *samples = (float *)buffer; // Samples internally stored as <float>s
|
||||||
float average = 0.0f; // Temporary average volume
|
float average = 0.0f; // Temporary average volume
|
||||||
|
|
@ -41,6 +41,8 @@ void ProcessAudio(void *buffer, unsigned int frames)
|
||||||
for (int i = 0; i < 399; i++) averageVolume[i] = averageVolume[i + 1];
|
for (int i = 0; i < 399; i++) averageVolume[i] = averageVolume[i + 1];
|
||||||
|
|
||||||
averageVolume[399] = average; // Adding last average value
|
averageVolume[399] = average; // Adding last average value
|
||||||
|
|
||||||
|
return frames;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
|
|
@ -57,7 +59,7 @@ int main(void)
|
||||||
|
|
||||||
InitAudioDevice(); // Initialize audio device
|
InitAudioDevice(); // Initialize audio device
|
||||||
|
|
||||||
AttachAudioMixedProcessor(ProcessAudio);
|
AttachAudioMixedProcessor(ProcessAudio, NULL);
|
||||||
|
|
||||||
Music music = LoadMusicStream("resources/country.mp3");
|
Music music = LoadMusicStream("resources/country.mp3");
|
||||||
Sound sound = LoadSound("resources/coin.wav");
|
Sound sound = LoadSound("resources/coin.wav");
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ float oldFrequency = 1.0f;
|
||||||
float sineIdx = 0.0f;
|
float sineIdx = 0.0f;
|
||||||
|
|
||||||
// Audio input processing callback
|
// Audio input processing callback
|
||||||
void AudioInputCallback(void *buffer, unsigned int frames)
|
unsigned int AudioInputCallback(void *buffer, unsigned int frames, void* userData)
|
||||||
{
|
{
|
||||||
audioFrequency = frequency + (audioFrequency - frequency)*0.95f;
|
audioFrequency = frequency + (audioFrequency - frequency)*0.95f;
|
||||||
|
|
||||||
|
|
@ -48,6 +48,8 @@ void AudioInputCallback(void *buffer, unsigned int frames)
|
||||||
sineIdx += incr;
|
sineIdx += incr;
|
||||||
if (sineIdx > 1.0f) sineIdx -= 1.0f;
|
if (sineIdx > 1.0f) sineIdx -= 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return frames;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
|
|
@ -69,7 +71,7 @@ int main(void)
|
||||||
// Init raw audio stream (sample rate: 44100, sample size: 16bit-short, channels: 1-mono)
|
// Init raw audio stream (sample rate: 44100, sample size: 16bit-short, channels: 1-mono)
|
||||||
AudioStream stream = LoadAudioStream(44100, 16, 1);
|
AudioStream stream = LoadAudioStream(44100, 16, 1);
|
||||||
|
|
||||||
SetAudioStreamCallback(stream, AudioInputCallback);
|
SetAudioStreamCallback(stream, AudioInputCallback, NULL);
|
||||||
|
|
||||||
// Buffer for the single cycle waveform we are synthesizing
|
// Buffer for the single cycle waveform we are synthesizing
|
||||||
short *data = (short *)malloc(sizeof(short)*MAX_SAMPLES);
|
short *data = (short *)malloc(sizeof(short)*MAX_SAMPLES);
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,8 @@ static unsigned int delayWriteIndex = 0;
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Module Functions Declaration
|
// Module Functions Declaration
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
static void AudioProcessEffectLPF(void *buffer, unsigned int frames); // Audio effect: lowpass filter
|
static unsigned int AudioProcessEffectLPF(void *buffer, unsigned int frames, void* userData); // Audio effect: lowpass filter
|
||||||
static void AudioProcessEffectDelay(void *buffer, unsigned int frames); // Audio effect: delay
|
static unsigned int AudioProcessEffectDelay(void *buffer, unsigned int frames, void* userData); // Audio effect: delay
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Program main entry point
|
// Program main entry point
|
||||||
|
|
@ -85,7 +85,7 @@ int main(void)
|
||||||
if (IsKeyPressed(KEY_F))
|
if (IsKeyPressed(KEY_F))
|
||||||
{
|
{
|
||||||
enableEffectLPF = !enableEffectLPF;
|
enableEffectLPF = !enableEffectLPF;
|
||||||
if (enableEffectLPF) AttachAudioStreamProcessor(music.stream, AudioProcessEffectLPF);
|
if (enableEffectLPF) AttachAudioStreamProcessor(music.stream, AudioProcessEffectLPF, NULL);
|
||||||
else DetachAudioStreamProcessor(music.stream, AudioProcessEffectLPF);
|
else DetachAudioStreamProcessor(music.stream, AudioProcessEffectLPF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -93,7 +93,7 @@ int main(void)
|
||||||
if (IsKeyPressed(KEY_D))
|
if (IsKeyPressed(KEY_D))
|
||||||
{
|
{
|
||||||
enableEffectDelay = !enableEffectDelay;
|
enableEffectDelay = !enableEffectDelay;
|
||||||
if (enableEffectDelay) AttachAudioStreamProcessor(music.stream, AudioProcessEffectDelay);
|
if (enableEffectDelay) AttachAudioStreamProcessor(music.stream, AudioProcessEffectDelay, NULL);
|
||||||
else DetachAudioStreamProcessor(music.stream, AudioProcessEffectDelay);
|
else DetachAudioStreamProcessor(music.stream, AudioProcessEffectDelay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -143,7 +143,7 @@ int main(void)
|
||||||
// Module Functions Definition
|
// Module Functions Definition
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Audio effect: lowpass filter
|
// Audio effect: lowpass filter
|
||||||
static void AudioProcessEffectLPF(void *buffer, unsigned int frames)
|
static unsigned int AudioProcessEffectLPF(void *buffer, unsigned int frames, void* userData)
|
||||||
{
|
{
|
||||||
static float low[2] = { 0.0f, 0.0f };
|
static float low[2] = { 0.0f, 0.0f };
|
||||||
static const float cutoff = 70.0f / 44100.0f; // 70 Hz lowpass filter
|
static const float cutoff = 70.0f / 44100.0f; // 70 Hz lowpass filter
|
||||||
|
|
@ -161,10 +161,12 @@ static void AudioProcessEffectLPF(void *buffer, unsigned int frames)
|
||||||
bufferData[i] = low[0];
|
bufferData[i] = low[0];
|
||||||
bufferData[i + 1] = low[1];
|
bufferData[i + 1] = low[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return frames;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Audio effect: delay
|
// Audio effect: delay
|
||||||
static void AudioProcessEffectDelay(void *buffer, unsigned int frames)
|
static unsigned int AudioProcessEffectDelay(void *buffer, unsigned int frames, void* userData)
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < frames*2; i += 2)
|
for (unsigned int i = 0; i < frames*2; i += 2)
|
||||||
{
|
{
|
||||||
|
|
@ -180,4 +182,6 @@ static void AudioProcessEffectDelay(void *buffer, unsigned int frames)
|
||||||
delayBuffer[delayWriteIndex++] = ((float *)buffer)[i + 1];
|
delayBuffer[delayWriteIndex++] = ((float *)buffer)[i + 1];
|
||||||
if (delayWriteIndex == delayBufferSize) delayWriteIndex = 0;
|
if (delayWriteIndex == delayBufferSize) delayWriteIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return frames;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
36
src/raudio.c
36
src/raudio.c
|
|
@ -343,6 +343,7 @@ struct rAudioBuffer {
|
||||||
ma_data_converter converter; // Audio data converter
|
ma_data_converter converter; // Audio data converter
|
||||||
|
|
||||||
AudioCallback callback; // Audio buffer callback for buffer filling on audio threads
|
AudioCallback callback; // Audio buffer callback for buffer filling on audio threads
|
||||||
|
void* userData; // User data forwarded to the callback
|
||||||
rAudioProcessor *processor; // Audio processor
|
rAudioProcessor *processor; // Audio processor
|
||||||
|
|
||||||
float volume; // Audio buffer volume
|
float volume; // Audio buffer volume
|
||||||
|
|
@ -369,6 +370,7 @@ struct rAudioBuffer {
|
||||||
// NOTE: Useful to apply effects to an AudioBuffer
|
// NOTE: Useful to apply effects to an AudioBuffer
|
||||||
struct rAudioProcessor {
|
struct rAudioProcessor {
|
||||||
AudioCallback process; // Processor callback function
|
AudioCallback process; // Processor callback function
|
||||||
|
void* userData; // User data forwarded to the callback
|
||||||
rAudioProcessor *next; // Next audio processor on the list
|
rAudioProcessor *next; // Next audio processor on the list
|
||||||
rAudioProcessor *prev; // Previous audio processor on the list
|
rAudioProcessor *prev; // Previous audio processor on the list
|
||||||
};
|
};
|
||||||
|
|
@ -445,6 +447,7 @@ void PlayAudioBuffer(AudioBuffer *buffer);
|
||||||
void StopAudioBuffer(AudioBuffer *buffer);
|
void StopAudioBuffer(AudioBuffer *buffer);
|
||||||
void PauseAudioBuffer(AudioBuffer *buffer);
|
void PauseAudioBuffer(AudioBuffer *buffer);
|
||||||
void ResumeAudioBuffer(AudioBuffer *buffer);
|
void ResumeAudioBuffer(AudioBuffer *buffer);
|
||||||
|
void SetAudioBufferLooping(AudioBuffer* buffer, bool loop);
|
||||||
void SetAudioBufferVolume(AudioBuffer *buffer, float volume);
|
void SetAudioBufferVolume(AudioBuffer *buffer, float volume);
|
||||||
void SetAudioBufferPitch(AudioBuffer *buffer, float pitch);
|
void SetAudioBufferPitch(AudioBuffer *buffer, float pitch);
|
||||||
void SetAudioBufferPan(AudioBuffer *buffer, float pan);
|
void SetAudioBufferPan(AudioBuffer *buffer, float pan);
|
||||||
|
|
@ -596,6 +599,7 @@ AudioBuffer *LoadAudioBuffer(ma_format format, ma_uint32 channels, ma_uint32 sam
|
||||||
audioBuffer->pan = 0.5f;
|
audioBuffer->pan = 0.5f;
|
||||||
|
|
||||||
audioBuffer->callback = NULL;
|
audioBuffer->callback = NULL;
|
||||||
|
audioBuffer->userData = NULL;
|
||||||
audioBuffer->processor = NULL;
|
audioBuffer->processor = NULL;
|
||||||
|
|
||||||
audioBuffer->playing = false;
|
audioBuffer->playing = false;
|
||||||
|
|
@ -684,6 +688,17 @@ void ResumeAudioBuffer(AudioBuffer *buffer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Turn looping on or off
|
||||||
|
void SetAudioBufferLooping(AudioBuffer* buffer, bool loop)
|
||||||
|
{
|
||||||
|
if (buffer != NULL)
|
||||||
|
{
|
||||||
|
ma_mutex_lock(&AUDIO.System.lock);
|
||||||
|
buffer->looping = loop;
|
||||||
|
ma_mutex_unlock(&AUDIO.System.lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Set volume for an audio buffer
|
// Set volume for an audio buffer
|
||||||
void SetAudioBufferVolume(AudioBuffer *buffer, float volume)
|
void SetAudioBufferVolume(AudioBuffer *buffer, float volume)
|
||||||
{
|
{
|
||||||
|
|
@ -2186,6 +2201,12 @@ void StopAudioStream(AudioStream stream)
|
||||||
StopAudioBuffer(stream.buffer);
|
StopAudioBuffer(stream.buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Turn looping on or off
|
||||||
|
void SetAudioStreamLooping(AudioStream stream, bool loop)
|
||||||
|
{
|
||||||
|
SetAudioBufferLooping(stream.buffer, loop);
|
||||||
|
}
|
||||||
|
|
||||||
// Set volume for audio stream (1.0 is max level)
|
// Set volume for audio stream (1.0 is max level)
|
||||||
void SetAudioStreamVolume(AudioStream stream, float volume)
|
void SetAudioStreamVolume(AudioStream stream, float volume)
|
||||||
{
|
{
|
||||||
|
|
@ -2211,12 +2232,13 @@ void SetAudioStreamBufferSizeDefault(int size)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Audio thread callback to request new data
|
// Audio thread callback to request new data
|
||||||
void SetAudioStreamCallback(AudioStream stream, AudioCallback callback)
|
void SetAudioStreamCallback(AudioStream stream, AudioCallback callback, void* userData)
|
||||||
{
|
{
|
||||||
if (stream.buffer != NULL)
|
if (stream.buffer != NULL)
|
||||||
{
|
{
|
||||||
ma_mutex_lock(&AUDIO.System.lock);
|
ma_mutex_lock(&AUDIO.System.lock);
|
||||||
stream.buffer->callback = callback;
|
stream.buffer->callback = callback;
|
||||||
|
stream.buffer->userData = userData;
|
||||||
ma_mutex_unlock(&AUDIO.System.lock);
|
ma_mutex_unlock(&AUDIO.System.lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2224,12 +2246,13 @@ void SetAudioStreamCallback(AudioStream stream, AudioCallback callback)
|
||||||
// Add processor to audio stream. Contrary to buffers, the order of processors is important
|
// Add processor to audio stream. Contrary to buffers, the order of processors is important
|
||||||
// The new processor must be added at the end. As there aren't supposed to be a lot of processors attached to
|
// The new processor must be added at the end. As there aren't supposed to be a lot of processors attached to
|
||||||
// a given stream, we iterate through the list to find the end. That way we don't need a pointer to the last element
|
// a given stream, we iterate through the list to find the end. That way we don't need a pointer to the last element
|
||||||
void AttachAudioStreamProcessor(AudioStream stream, AudioCallback process)
|
void AttachAudioStreamProcessor(AudioStream stream, AudioCallback process, void* userData)
|
||||||
{
|
{
|
||||||
ma_mutex_lock(&AUDIO.System.lock);
|
ma_mutex_lock(&AUDIO.System.lock);
|
||||||
|
|
||||||
rAudioProcessor *processor = (rAudioProcessor *)RL_CALLOC(1, sizeof(rAudioProcessor));
|
rAudioProcessor *processor = (rAudioProcessor *)RL_CALLOC(1, sizeof(rAudioProcessor));
|
||||||
processor->process = process;
|
processor->process = process;
|
||||||
|
processor->userData = userData;
|
||||||
|
|
||||||
rAudioProcessor *last = stream.buffer->processor;
|
rAudioProcessor *last = stream.buffer->processor;
|
||||||
|
|
||||||
|
|
@ -2277,12 +2300,13 @@ void DetachAudioStreamProcessor(AudioStream stream, AudioCallback process)
|
||||||
// Add processor to audio pipeline. Order of processors is important
|
// Add processor to audio pipeline. Order of processors is important
|
||||||
// Works the same way as {Attach,Detach}AudioStreamProcessor() functions, except
|
// Works the same way as {Attach,Detach}AudioStreamProcessor() functions, except
|
||||||
// these two work on the already mixed output just before sending it to the sound hardware
|
// these two work on the already mixed output just before sending it to the sound hardware
|
||||||
void AttachAudioMixedProcessor(AudioCallback process)
|
void AttachAudioMixedProcessor(AudioCallback process, void* userData)
|
||||||
{
|
{
|
||||||
ma_mutex_lock(&AUDIO.System.lock);
|
ma_mutex_lock(&AUDIO.System.lock);
|
||||||
|
|
||||||
rAudioProcessor *processor = (rAudioProcessor *)RL_CALLOC(1, sizeof(rAudioProcessor));
|
rAudioProcessor *processor = (rAudioProcessor *)RL_CALLOC(1, sizeof(rAudioProcessor));
|
||||||
processor->process = process;
|
processor->process = process;
|
||||||
|
processor->userData = userData;
|
||||||
|
|
||||||
rAudioProcessor *last = AUDIO.mixedProcessor;
|
rAudioProcessor *last = AUDIO.mixedProcessor;
|
||||||
|
|
||||||
|
|
@ -2344,7 +2368,7 @@ static ma_uint32 ReadAudioBufferFramesInInternalFormat(AudioBuffer *audioBuffer,
|
||||||
// Using audio buffer callback
|
// Using audio buffer callback
|
||||||
if (audioBuffer->callback)
|
if (audioBuffer->callback)
|
||||||
{
|
{
|
||||||
audioBuffer->callback(framesOut, frameCount);
|
frameCount = audioBuffer->callback(framesOut, frameCount, audioBuffer->userData);
|
||||||
audioBuffer->framesProcessed += frameCount;
|
audioBuffer->framesProcessed += frameCount;
|
||||||
|
|
||||||
return frameCount;
|
return frameCount;
|
||||||
|
|
@ -2527,7 +2551,7 @@ static void OnSendAudioDataToDevice(ma_device *pDevice, void *pFramesOut, const
|
||||||
rAudioProcessor *processor = audioBuffer->processor;
|
rAudioProcessor *processor = audioBuffer->processor;
|
||||||
while (processor)
|
while (processor)
|
||||||
{
|
{
|
||||||
processor->process(framesIn, framesJustRead);
|
processor->process(framesIn, framesJustRead, processor->userData);
|
||||||
processor = processor->next;
|
processor = processor->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2571,7 +2595,7 @@ static void OnSendAudioDataToDevice(ma_device *pDevice, void *pFramesOut, const
|
||||||
rAudioProcessor *processor = AUDIO.mixedProcessor;
|
rAudioProcessor *processor = AUDIO.mixedProcessor;
|
||||||
while (processor)
|
while (processor)
|
||||||
{
|
{
|
||||||
processor->process(pFramesOut, frameCount);
|
processor->process(pFramesOut, frameCount, processor->userData);
|
||||||
processor = processor->next;
|
processor = processor->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1602,7 +1602,7 @@ RLAPI RayCollision GetRayCollisionQuad(Ray ray, Vector3 p1, Vector3 p2, Vector3
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Audio Loading and Playing Functions (Module: audio)
|
// Audio Loading and Playing Functions (Module: audio)
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
typedef void (*AudioCallback)(void *bufferData, unsigned int frames);
|
typedef unsigned int (*AudioCallback)(void *bufferData, unsigned int frames, void* userData);
|
||||||
|
|
||||||
// Audio device management functions
|
// Audio device management functions
|
||||||
RLAPI void InitAudioDevice(void); // Initialize audio device and context
|
RLAPI void InitAudioDevice(void); // Initialize audio device and context
|
||||||
|
|
@ -1670,16 +1670,17 @@ RLAPI void PauseAudioStream(AudioStream stream); // Pause a
|
||||||
RLAPI void ResumeAudioStream(AudioStream stream); // Resume audio stream
|
RLAPI void ResumeAudioStream(AudioStream stream); // Resume audio stream
|
||||||
RLAPI bool IsAudioStreamPlaying(AudioStream stream); // Check if audio stream is playing
|
RLAPI bool IsAudioStreamPlaying(AudioStream stream); // Check if audio stream is playing
|
||||||
RLAPI void StopAudioStream(AudioStream stream); // Stop audio stream
|
RLAPI void StopAudioStream(AudioStream stream); // Stop audio stream
|
||||||
|
RLAPI void SetAudioStreamLooping(AudioStream stream, bool loop); // Turn looping on or off
|
||||||
RLAPI void SetAudioStreamVolume(AudioStream stream, float volume); // Set volume for audio stream (1.0 is max level)
|
RLAPI void SetAudioStreamVolume(AudioStream stream, float volume); // Set volume for audio stream (1.0 is max level)
|
||||||
RLAPI void SetAudioStreamPitch(AudioStream stream, float pitch); // Set pitch for audio stream (1.0 is base level)
|
RLAPI void SetAudioStreamPitch(AudioStream stream, float pitch); // Set pitch for audio stream (1.0 is base level)
|
||||||
RLAPI void SetAudioStreamPan(AudioStream stream, float pan); // Set pan for audio stream (0.5 is centered)
|
RLAPI void SetAudioStreamPan(AudioStream stream, float pan); // Set pan for audio stream (0.5 is centered)
|
||||||
RLAPI void SetAudioStreamBufferSizeDefault(int size); // Default size for new audio streams
|
RLAPI void SetAudioStreamBufferSizeDefault(int size); // Default size for new audio streams
|
||||||
RLAPI void SetAudioStreamCallback(AudioStream stream, AudioCallback callback); // Audio thread callback to request new data
|
RLAPI void SetAudioStreamCallback(AudioStream stream, AudioCallback callback, void* userData); // Audio thread callback to request new data
|
||||||
|
|
||||||
RLAPI void AttachAudioStreamProcessor(AudioStream stream, AudioCallback processor); // Attach audio stream processor to stream, receives the samples as 'float'
|
RLAPI void AttachAudioStreamProcessor(AudioStream stream, AudioCallback processor, void* userData); // Attach audio stream processor to stream, receives the samples as 'float'
|
||||||
RLAPI void DetachAudioStreamProcessor(AudioStream stream, AudioCallback processor); // Detach audio stream processor from stream
|
RLAPI void DetachAudioStreamProcessor(AudioStream stream, AudioCallback processor); // Detach audio stream processor from stream
|
||||||
|
|
||||||
RLAPI void AttachAudioMixedProcessor(AudioCallback processor); // Attach audio stream processor to the entire audio pipeline, receives the samples as 'float'
|
RLAPI void AttachAudioMixedProcessor(AudioCallback processor, void* userData); // Attach audio stream processor to the entire audio pipeline, receives the samples as 'float'
|
||||||
RLAPI void DetachAudioMixedProcessor(AudioCallback processor); // Detach audio stream processor from the entire audio pipeline
|
RLAPI void DetachAudioMixedProcessor(AudioCallback processor); // Detach audio stream processor from the entire audio pipeline
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user