ADDED: Audio stream input callback #2212 -WIP-
WARNING: This addition is based on a PR and it's still under review, not sure if it will be maintained in the future. In general, raylib tries to avoid callbacks usage mechanisms.
This commit is contained in:
parent
bcd84cd36d
commit
381236051f
3 changed files with 64 additions and 5 deletions
|
@ -20,6 +20,35 @@
|
|||
#define MAX_SAMPLES 512
|
||||
#define MAX_SAMPLES_PER_UPDATE 4096
|
||||
|
||||
// Cycles per second (hz)
|
||||
float frequency = 440.0f;
|
||||
|
||||
// Audio frequency, for smoothing
|
||||
float audioFrequency = 440.0f;
|
||||
|
||||
// Previous value, used to test if sine needs to be rewritten, and to smoothly modulate frequency
|
||||
float oldFrequency = 1.0f;
|
||||
|
||||
// Index for audio rendering
|
||||
float sineIdx = 0.0f;
|
||||
|
||||
void AudioCallback(void *buffer, unsigned int frames)
|
||||
{
|
||||
audioFrequency = frequency + (audioFrequency - frequency)*0.95f;
|
||||
audioFrequency += 1.0f;
|
||||
audioFrequency -= 1.0f;
|
||||
float incr = audioFrequency/44100.0f;
|
||||
short *d = (short *)buffer;
|
||||
|
||||
for (int i = 0; i < frames; i++)
|
||||
{
|
||||
d[i] = (short)(32000.0f*sinf(2*PI*sineIdx));
|
||||
sineIdx += incr;
|
||||
if (sineIdx > 1.0f) sineIdx -= 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
|
@ -33,9 +62,11 @@ int main(void)
|
|||
|
||||
SetAudioStreamBufferSizeDefault(MAX_SAMPLES_PER_UPDATE);
|
||||
|
||||
// Init raw audio stream (sample rate: 22050, 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);
|
||||
|
||||
SetAudioStreamCallback(stream, &AudioCallback);
|
||||
|
||||
// Buffer for the single cycle waveform we are synthesizing
|
||||
short *data = (short *)malloc(sizeof(short)*MAX_SAMPLES);
|
||||
|
||||
|
@ -47,6 +78,7 @@ int main(void)
|
|||
// Position read in to determine next frequency
|
||||
Vector2 mousePosition = { -100.0f, -100.0f };
|
||||
|
||||
/*
|
||||
// Cycles per second (hz)
|
||||
float frequency = 440.0f;
|
||||
|
||||
|
@ -55,6 +87,7 @@ int main(void)
|
|||
|
||||
// Cursor to read and copy the samples of the sine wave buffer
|
||||
int readCursor = 0;
|
||||
*/
|
||||
|
||||
// Computed size in samples of the sine wave
|
||||
int waveLength = 1;
|
||||
|
@ -82,7 +115,7 @@ int main(void)
|
|||
SetAudioStreamPan(stream, pan);
|
||||
}
|
||||
|
||||
// Rewrite the sine wave.
|
||||
// Rewrite the sine wave
|
||||
// Compute two cycles to allow the buffer padding, simplifying any modulation, resampling, etc.
|
||||
if (frequency != oldFrequency)
|
||||
{
|
||||
|
@ -92,17 +125,18 @@ int main(void)
|
|||
if (waveLength > MAX_SAMPLES/2) waveLength = MAX_SAMPLES/2;
|
||||
if (waveLength < 1) waveLength = 1;
|
||||
|
||||
// Write sine wave.
|
||||
// Write sine wave
|
||||
for (int i = 0; i < waveLength*2; i++)
|
||||
{
|
||||
data[i] = (short)(sinf(((2*PI*(float)i/waveLength)))*32000);
|
||||
}
|
||||
|
||||
// Scale read cursor's position to minimize transition artifacts
|
||||
readCursor = (int)(readCursor * ((float)waveLength / (float)oldWavelength));
|
||||
//readCursor = (int)(readCursor * ((float)waveLength / (float)oldWavelength));
|
||||
oldFrequency = frequency;
|
||||
}
|
||||
|
||||
/*
|
||||
// Refill audio stream if required
|
||||
if (IsAudioStreamProcessed(stream))
|
||||
{
|
||||
|
@ -131,6 +165,7 @@ int main(void)
|
|||
// Copy finished frame to audio stream
|
||||
UpdateAudioStream(stream, writeBuf, MAX_SAMPLES_PER_UPDATE);
|
||||
}
|
||||
*/
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
|
|
22
src/raudio.c
22
src/raudio.c
|
@ -311,10 +311,12 @@ typedef enum {
|
|||
AUDIO_BUFFER_USAGE_STREAM
|
||||
} AudioBufferUsage;
|
||||
|
||||
// Audio buffer structure
|
||||
// Audio buffer struct
|
||||
struct rAudioBuffer {
|
||||
ma_data_converter converter; // Audio data converter
|
||||
|
||||
AudioStreamCallback callback; // Audio buffer callback for buffer filling on audio threads
|
||||
|
||||
float volume; // Audio buffer volume
|
||||
float pitch; // Audio buffer pitch
|
||||
float pan; // Audio buffer pan (0.0f to 1.0f)
|
||||
|
@ -556,9 +558,12 @@ AudioBuffer *LoadAudioBuffer(ma_format format, ma_uint32 channels, ma_uint32 sam
|
|||
audioBuffer->pitch = 1.0f;
|
||||
audioBuffer->pan = 0.5f;
|
||||
|
||||
audioBuffer->callback = NULL;
|
||||
|
||||
audioBuffer->playing = false;
|
||||
audioBuffer->paused = false;
|
||||
audioBuffer->looping = false;
|
||||
|
||||
audioBuffer->usage = usage;
|
||||
audioBuffer->frameCursorPos = 0;
|
||||
audioBuffer->sizeInFrames = sizeInFrames;
|
||||
|
@ -2028,6 +2033,12 @@ void SetAudioStreamBufferSizeDefault(int size)
|
|||
AUDIO.Buffer.defaultSize = size;
|
||||
}
|
||||
|
||||
// Audio thread callback to request new data
|
||||
void SetAudioStreamCallback(AudioStream stream, AudioStreamCallback callback)
|
||||
{
|
||||
if (stream.buffer != NULL) stream.buffer->callback = callback;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module specific Functions Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
|
@ -2041,6 +2052,15 @@ static void OnLog(void *pUserData, ma_uint32 level, const char *pMessage)
|
|||
// Reads audio data from an AudioBuffer object in internal format.
|
||||
static ma_uint32 ReadAudioBufferFramesInInternalFormat(AudioBuffer *audioBuffer, void *framesOut, ma_uint32 frameCount)
|
||||
{
|
||||
// Using audio buffer callback
|
||||
if (audioBuffer->callback)
|
||||
{
|
||||
audioBuffer->callback(framesOut, frameCount);
|
||||
audioBuffer->framesProcessed += frameCount;
|
||||
|
||||
return frameCount;
|
||||
}
|
||||
|
||||
ma_uint32 subBufferSizeInFrames = (audioBuffer->sizeInFrames > 1)? audioBuffer->sizeInFrames/2 : audioBuffer->sizeInFrames;
|
||||
ma_uint32 currentSubBufferIndex = audioBuffer->frameCursorPos/subBufferSizeInFrames;
|
||||
|
||||
|
|
|
@ -425,6 +425,8 @@ typedef struct Wave {
|
|||
void *data; // Buffer data pointer
|
||||
} Wave;
|
||||
|
||||
// Opaque structs declaration
|
||||
// NOTE: Actual structs are defined internally in raudio module
|
||||
typedef struct rAudioBuffer rAudioBuffer;
|
||||
|
||||
// AudioStream, custom audio stream
|
||||
|
@ -1472,6 +1474,7 @@ RLAPI RayCollision GetRayCollisionQuad(Ray ray, Vector3 p1, Vector3 p2, Vector3
|
|||
//------------------------------------------------------------------------------------
|
||||
// Audio Loading and Playing Functions (Module: audio)
|
||||
//------------------------------------------------------------------------------------
|
||||
typedef void (*AudioStreamCallback)(void *bufferData, unsigned int frames);
|
||||
|
||||
// Audio device management functions
|
||||
RLAPI void InitAudioDevice(void); // Initialize audio device and context
|
||||
|
@ -1539,6 +1542,7 @@ RLAPI void SetAudioStreamVolume(AudioStream stream, float volume); // Set vol
|
|||
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 SetAudioStreamBufferSizeDefault(int size); // Default size for new audio streams
|
||||
RLAPI void SetAudioStreamCallback(AudioStream stream, AudioStreamCallback callback); // Audio thread callback to request new data
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue