Parcourir la source

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.
Ray il y a 3 ans
Parent
commit
381236051f
3 fichiers modifiés avec 64 ajouts et 5 suppressions
  1. 39 4
      examples/audio/audio_raw_stream.c
  2. 21 1
      src/raudio.c
  3. 4 0
      src/raylib.h

+ 39 - 4
examples/audio/audio_raw_stream.c

@@ -20,6 +20,35 @@
 #define MAX_SAMPLES               512
 #define MAX_SAMPLES               512
 #define MAX_SAMPLES_PER_UPDATE   4096
 #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)
 int main(void)
 {
 {
     // Initialization
     // Initialization
@@ -33,9 +62,11 @@ int main(void)
 
 
     SetAudioStreamBufferSizeDefault(MAX_SAMPLES_PER_UPDATE);
     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);
     AudioStream stream = LoadAudioStream(44100, 16, 1);
 
 
+    SetAudioStreamCallback(stream, &AudioCallback);
+
     // 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);
 
 
@@ -47,6 +78,7 @@ int main(void)
     // Position read in to determine next frequency
     // Position read in to determine next frequency
     Vector2 mousePosition = { -100.0f, -100.0f };
     Vector2 mousePosition = { -100.0f, -100.0f };
 
 
+    /*
     // Cycles per second (hz)
     // Cycles per second (hz)
     float frequency = 440.0f;
     float frequency = 440.0f;
 
 
@@ -55,6 +87,7 @@ int main(void)
 
 
     // Cursor to read and copy the samples of the sine wave buffer
     // Cursor to read and copy the samples of the sine wave buffer
     int readCursor = 0;
     int readCursor = 0;
+    */
 
 
     // Computed size in samples of the sine wave
     // Computed size in samples of the sine wave
     int waveLength = 1;
     int waveLength = 1;
@@ -82,7 +115,7 @@ int main(void)
             SetAudioStreamPan(stream, pan);
             SetAudioStreamPan(stream, pan);
         }
         }
 
 
-        // Rewrite the sine wave.
+        // Rewrite the sine wave
         // Compute two cycles to allow the buffer padding, simplifying any modulation, resampling, etc.
         // Compute two cycles to allow the buffer padding, simplifying any modulation, resampling, etc.
         if (frequency != oldFrequency)
         if (frequency != oldFrequency)
         {
         {
@@ -92,17 +125,18 @@ int main(void)
             if (waveLength > MAX_SAMPLES/2) waveLength = MAX_SAMPLES/2;
             if (waveLength > MAX_SAMPLES/2) waveLength = MAX_SAMPLES/2;
             if (waveLength < 1) waveLength = 1;
             if (waveLength < 1) waveLength = 1;
 
 
-            // Write sine wave.
+            // Write sine wave
             for (int i = 0; i < waveLength*2; i++)
             for (int i = 0; i < waveLength*2; i++)
             {
             {
                 data[i] = (short)(sinf(((2*PI*(float)i/waveLength)))*32000);
                 data[i] = (short)(sinf(((2*PI*(float)i/waveLength)))*32000);
             }
             }
 
 
             // Scale read cursor's position to minimize transition artifacts
             // 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;
             oldFrequency = frequency;
         }
         }
 
 
+        /*
         // Refill audio stream if required
         // Refill audio stream if required
         if (IsAudioStreamProcessed(stream))
         if (IsAudioStreamProcessed(stream))
         {
         {
@@ -131,6 +165,7 @@ int main(void)
             // Copy finished frame to audio stream
             // Copy finished frame to audio stream
             UpdateAudioStream(stream, writeBuf, MAX_SAMPLES_PER_UPDATE);
             UpdateAudioStream(stream, writeBuf, MAX_SAMPLES_PER_UPDATE);
         }
         }
+        */
         //----------------------------------------------------------------------------------
         //----------------------------------------------------------------------------------
 
 
         // Draw
         // Draw

+ 21 - 1
src/raudio.c

@@ -311,9 +311,11 @@ typedef enum {
     AUDIO_BUFFER_USAGE_STREAM
     AUDIO_BUFFER_USAGE_STREAM
 } AudioBufferUsage;
 } AudioBufferUsage;
 
 
-// Audio buffer structure
+// Audio buffer struct
 struct rAudioBuffer {
 struct rAudioBuffer {
     ma_data_converter converter;    // Audio data converter
     ma_data_converter converter;    // Audio data converter
+    
+    AudioStreamCallback callback;   // Audio buffer callback for buffer filling on audio threads
 
 
     float volume;                   // Audio buffer volume
     float volume;                   // Audio buffer volume
     float pitch;                    // Audio buffer pitch
     float pitch;                    // Audio buffer pitch
@@ -555,10 +557,13 @@ AudioBuffer *LoadAudioBuffer(ma_format format, ma_uint32 channels, ma_uint32 sam
     audioBuffer->volume = 1.0f;
     audioBuffer->volume = 1.0f;
     audioBuffer->pitch = 1.0f;
     audioBuffer->pitch = 1.0f;
     audioBuffer->pan = 0.5f;
     audioBuffer->pan = 0.5f;
+    
+    audioBuffer->callback = NULL;
 
 
     audioBuffer->playing = false;
     audioBuffer->playing = false;
     audioBuffer->paused = false;
     audioBuffer->paused = false;
     audioBuffer->looping = false;
     audioBuffer->looping = false;
+ 
     audioBuffer->usage = usage;
     audioBuffer->usage = usage;
     audioBuffer->frameCursorPos = 0;
     audioBuffer->frameCursorPos = 0;
     audioBuffer->sizeInFrames = sizeInFrames;
     audioBuffer->sizeInFrames = sizeInFrames;
@@ -2028,6 +2033,12 @@ void SetAudioStreamBufferSizeDefault(int size)
     AUDIO.Buffer.defaultSize = 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
 // 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.
 // Reads audio data from an AudioBuffer object in internal format.
 static ma_uint32 ReadAudioBufferFramesInInternalFormat(AudioBuffer *audioBuffer, void *framesOut, ma_uint32 frameCount)
 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 subBufferSizeInFrames = (audioBuffer->sizeInFrames > 1)? audioBuffer->sizeInFrames/2 : audioBuffer->sizeInFrames;
     ma_uint32 currentSubBufferIndex = audioBuffer->frameCursorPos/subBufferSizeInFrames;
     ma_uint32 currentSubBufferIndex = audioBuffer->frameCursorPos/subBufferSizeInFrames;
 
 

+ 4 - 0
src/raylib.h

@@ -425,6 +425,8 @@ typedef struct Wave {
     void *data;                 // Buffer data pointer
     void *data;                 // Buffer data pointer
 } Wave;
 } Wave;
 
 
+// Opaque structs declaration
+// NOTE: Actual structs are defined internally in raudio module
 typedef struct rAudioBuffer rAudioBuffer;
 typedef struct rAudioBuffer rAudioBuffer;
 
 
 // AudioStream, custom audio stream
 // 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)
 // Audio Loading and Playing Functions (Module: audio)
 //------------------------------------------------------------------------------------
 //------------------------------------------------------------------------------------
+typedef void (*AudioStreamCallback)(void *bufferData, unsigned int frames);
 
 
 // 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
@@ -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 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, AudioStreamCallback callback);  // Audio thread callback to request new data
 
 
 #if defined(__cplusplus)
 #if defined(__cplusplus)
 }
 }