Преглед на файлове

Add panning to raudio and update audio_raw_stream example. (#2205)

* Add panning to raudio and update audio_raw_stream example.

* remove pan smoothing, code formatting changes following pull request comments

Co-authored-by: Ray <[email protected]>
ptarabbia преди 3 години
родител
ревизия
5ac07122bd
променени са 4 файла, в които са добавени 74 реда и са изтрити 9 реда
  1. 4 1
      examples/audio/audio_raw_stream.c
  2. 64 8
      src/raudio.c
  3. 3 0
      src/raudio.h
  4. 3 0
      src/raylib.h

+ 4 - 1
examples/audio/audio_raw_stream.c

@@ -77,6 +77,9 @@ int main(void)
         {
             float fp = (float)(mousePosition.y);
             frequency = 40.0f + (float)(fp);
+
+            float pan = (float)(mousePosition.x) / (float)screenWidth;
+            SetAudioStreamPan(stream, pan);
         }
 
         // Rewrite the sine wave.
@@ -137,7 +140,7 @@ int main(void)
             ClearBackground(RAYWHITE);
 
             DrawText(TextFormat("sine frequency: %i",(int)frequency), GetScreenWidth() - 220, 10, 20, RED);
-            DrawText("click mouse button to change frequency", 10, 10, 20, DARKGRAY);
+            DrawText("click mouse button to change frequency or pan", 10, 10, 20, DARKGRAY);
 
             // Draw the current buffer state proportionate to the screen
             for (int i = 0; i < screenWidth; i++)

+ 64 - 8
src/raudio.c

@@ -317,6 +317,7 @@ struct rAudioBuffer {
 
     float volume;                   // Audio buffer volume
     float pitch;                    // Audio buffer pitch
+    float pan;                      // Audio buffer pan (0 to 1)
 
     bool playing;                   // Audio buffer state: AUDIO_PLAYING
     bool paused;                    // Audio buffer state: AUDIO_PAUSED
@@ -373,7 +374,7 @@ static AudioData AUDIO = {          // Global AUDIO context
 //----------------------------------------------------------------------------------
 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 void MixAudioFrames(float *framesOut, const float *framesIn, ma_uint32 frameCount, float localVolume);
+static void MixAudioFrames(float *framesOut, const float *framesIn, ma_uint32 frameCount, AudioBuffer *buffer);
 
 #if defined(RAUDIO_STANDALONE)
 static bool IsFileExtension(const char *fileName, const char *ext); // Check file extension
@@ -397,6 +398,7 @@ void StopAudioBuffer(AudioBuffer *buffer);
 void PauseAudioBuffer(AudioBuffer *buffer);
 void ResumeAudioBuffer(AudioBuffer *buffer);
 void SetAudioBufferVolume(AudioBuffer *buffer, float volume);
+void SetAudioBufferPan(AudioBuffer *buffer, float pan);
 void SetAudioBufferPitch(AudioBuffer *buffer, float pitch);
 void TrackAudioBuffer(AudioBuffer *buffer);
 void UntrackAudioBuffer(AudioBuffer *buffer);
@@ -553,6 +555,8 @@ AudioBuffer *LoadAudioBuffer(ma_format format, ma_uint32 channels, ma_uint32 sam
     // Init audio buffer values
     audioBuffer->volume = 1.0f;
     audioBuffer->pitch = 1.0f;
+    audioBuffer->pan = 0.5f;
+
     audioBuffer->playing = false;
     audioBuffer->paused = false;
     audioBuffer->looping = false;
@@ -641,6 +645,12 @@ void SetAudioBufferVolume(AudioBuffer *buffer, float volume)
     if (buffer != NULL) buffer->volume = volume;
 }
 
+// Set pan for an audio buffer
+void SetAudioBufferPan(AudioBuffer *buffer, float pan)
+{
+    if (buffer != NULL) buffer->pan = pan;
+}
+
 // Set pitch for an audio buffer
 void SetAudioBufferPitch(AudioBuffer *buffer, float pitch)
 {
@@ -1048,6 +1058,8 @@ void PlaySoundMulti(Sound sound)
 
     SetAudioBufferVolume(AUDIO.MultiChannel.pool[index], sound.stream.buffer->volume);
     SetAudioBufferPitch(AUDIO.MultiChannel.pool[index], sound.stream.buffer->pitch);
+    SetAudioBufferPan(AUDIO.MultiChannel.pool[index], sound.stream.buffer->pan);
+
     AUDIO.MultiChannel.pool[index]->looping = sound.stream.buffer->looping;
     AUDIO.MultiChannel.pool[index]->usage = sound.stream.buffer->usage;
     AUDIO.MultiChannel.pool[index]->isSubBufferProcessed[0] = false;
@@ -1113,6 +1125,12 @@ void SetSoundPitch(Sound sound, float pitch)
     SetAudioBufferPitch(sound.stream.buffer, pitch);
 }
 
+// Set pan for a sound
+void SetSoundPan(Sound sound, float pan)
+{
+    SetAudioBufferPan(sound.stream.buffer, pan);
+}
+
 // Convert wave data to desired format
 void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels)
 {
@@ -1809,6 +1827,12 @@ void SetMusicPitch(Music music, float pitch)
     SetAudioBufferPitch(music.stream.buffer, pitch);
 }
 
+// Set pan for a music
+void SetMusicPan(Music music, float pan)
+{
+    SetAudioBufferPan(music.stream.buffer, pan);
+}
+
 // Get music time length (in seconds)
 float GetMusicTimeLength(Music music)
 {
@@ -1989,6 +2013,14 @@ void SetAudioStreamPitch(AudioStream stream, float pitch)
     SetAudioBufferPitch(stream.buffer, pitch);
 }
 
+// Set pan for audio stream
+void SetAudioStreamPan(AudioStream stream, float pan)
+{
+    if (pan < 0.0f) pan = 0.0f; else if (pan > 1.0f) pan = 1.0f;
+    SetAudioBufferPan(stream.buffer, pan);
+}
+
+
 // Default size for new audio streams
 void SetAudioStreamBufferSizeDefault(int size)
 {
@@ -2184,7 +2216,7 @@ static void OnSendAudioDataToDevice(ma_device *pDevice, void *pFramesOut, const
                         float *framesOut = (float *)pFramesOut + (framesRead*AUDIO.System.device.playback.channels);
                         float *framesIn = tempBuffer;
 
-                        MixAudioFrames(framesOut, framesIn, framesJustRead, audioBuffer->volume);
+                        MixAudioFrames(framesOut, framesIn, framesJustRead, audioBuffer);
 
                         framesToRead -= framesJustRead;
                         framesRead += framesJustRead;
@@ -2226,16 +2258,40 @@ static void OnSendAudioDataToDevice(ma_device *pDevice, void *pFramesOut, const
 
 // 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, ma_uint32 frameCount, float localVolume)
+static void MixAudioFrames(float *framesOut, const float *framesIn, ma_uint32 frameCount, AudioBuffer *buffer)
 {
-    for (ma_uint32 iFrame = 0; iFrame < frameCount; ++iFrame)
+    const float localVolume = buffer->volume;
+
+    const ma_uint32 nChannels = AUDIO.System.device.playback.channels;
+    if (nChannels == 2)
+    {
+        const float left = buffer->pan;
+        const float right = 1.0f - left;
+
+        // fast sine approximation in [0..1] for pan law: y = 0.5f * x * (3 - x * x);
+        const float levels[2] = { localVolume*0.5f*left*(3.0f-left*left), localVolume*0.5f*right*(3.0f-right*right) };
+
+        float *frameOut = framesOut;
+        const float *frameIn = framesIn;
+        for (ma_uint32 iFrame = 0; iFrame < frameCount; ++iFrame)
+        {
+            frameOut[0] += (frameIn[0]*levels[0]);
+            frameOut[1] += (frameIn[1]*levels[1]);
+            frameOut += 2;
+            frameIn += 2;
+        }
+    }
+    else // pan is kinda meaningless
     {
-        for (ma_uint32 iChannel = 0; iChannel < AUDIO.System.device.playback.channels; ++iChannel)
+        for (ma_uint32 iFrame = 0; iFrame < frameCount; ++iFrame)
         {
-            float *frameOut = framesOut + (iFrame*AUDIO.System.device.playback.channels);
-            const float *frameIn = framesIn + (iFrame*AUDIO.System.device.playback.channels);
+            for (ma_uint32 iChannel = 0; iChannel < nChannels; ++iChannel)
+            {
+                float *frameOut = framesOut + (iFrame * nChannels);
+                const float *frameIn = framesIn + (iFrame * nChannels);
 
-            frameOut[iChannel] += (frameIn[iChannel]*localVolume);
+                frameOut[iChannel] += (frameIn[iChannel] * localVolume);
+            }
         }
     }
 }

+ 3 - 0
src/raudio.h

@@ -155,6 +155,7 @@ int GetSoundsPlaying(void);                                     // Get number of
 bool IsSoundPlaying(Sound sound);                               // Check if a sound is currently playing
 void SetSoundVolume(Sound sound, float volume);                 // Set volume for a sound (1.0 is max level)
 void SetSoundPitch(Sound sound, float pitch);                   // Set pitch for a sound (1.0 is base level)
+void SetSoundPan(Sound sound, float pan);                       // Set pan for a sound (0.0 to 1.0, 0.5=center)
 void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels);  // Convert wave data to desired format
 Wave WaveCopy(Wave wave);                                       // Copy a wave to a new wave
 void WaveCrop(Wave *wave, int initSample, int finalSample);     // Crop a wave to defined samples range
@@ -173,6 +174,7 @@ void PauseMusicStream(Music music);                             // Pause music p
 void ResumeMusicStream(Music music);                            // Resume playing paused music
 void SeekMusicStream(Music music, float position);              // Seek music to a position (in seconds)
 void SetMusicVolume(Music music, float volume);                 // Set volume for music (1.0 is max level)
+void SetMusicPan(Music sound, float pan);                       // Set pan for a music (0.0 to 1.0, 0.5=center)
 void SetMusicPitch(Music music, float pitch);                   // Set pitch for a music (1.0 is base level)
 float GetMusicTimeLength(Music music);                          // Get music time length (in seconds)
 float GetMusicTimePlayed(Music music);                          // Get current music time played (in seconds)
@@ -189,6 +191,7 @@ bool IsAudioStreamPlaying(AudioStream stream);                  // Check if audi
 void StopAudioStream(AudioStream stream);                       // Stop audio stream
 void SetAudioStreamVolume(AudioStream stream, float volume);    // Set volume for audio stream (1.0 is max level)
 void SetAudioStreamPitch(AudioStream stream, float pitch);      // Set pitch for audio stream (1.0 is base level)
+void SetAudioStreamPan(AudioStream strean, float pan);          // Set pan for audio stream  (0.0 to 1.0, 0.5=center)
 void SetAudioStreamBufferSizeDefault(int size);                 // Default size for new audio streams
 
 #ifdef __cplusplus

+ 3 - 0
src/raylib.h

@@ -1498,6 +1498,7 @@ RLAPI void StopSoundMulti(void);                                      // Stop an
 RLAPI int GetSoundsPlaying(void);                                     // Get number of sounds playing in the multichannel
 RLAPI bool IsSoundPlaying(Sound sound);                               // Check if a sound is currently playing
 RLAPI void SetSoundVolume(Sound sound, float volume);                 // Set volume for a sound (1.0 is max level)
+RLAPI void SetSoundPan(Sound sound, float pan);                       // Set pan for a sound (0.5 = center)
 RLAPI void SetSoundPitch(Sound sound, float pitch);                   // Set pitch for a sound (1.0 is base level)
 RLAPI void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels); // Convert wave data to desired format
 RLAPI Wave WaveCopy(Wave wave);                                       // Copy a wave to a new wave
@@ -1517,6 +1518,7 @@ RLAPI void PauseMusicStream(Music music);                             // Pause m
 RLAPI void ResumeMusicStream(Music music);                            // Resume playing paused music
 RLAPI void SeekMusicStream(Music music, float position);              // Seek music to a position (in seconds)
 RLAPI void SetMusicVolume(Music music, float volume);                 // Set volume for music (1.0 is max level)
+RLAPI void SetMusicPan(Music music, float pan);                       // Set pan for a music (0.5 = center)
 RLAPI void SetMusicPitch(Music music, float pitch);                   // Set pitch for a music (1.0 is base level)
 RLAPI float GetMusicTimeLength(Music music);                          // Get music time length (in seconds)
 RLAPI float GetMusicTimePlayed(Music music);                          // Get current music time played (in seconds)
@@ -1533,6 +1535,7 @@ RLAPI bool IsAudioStreamPlaying(AudioStream stream);                  // Check i
 RLAPI void StopAudioStream(AudioStream stream);                       // Stop audio stream
 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 SetAudioStreamPan(AudioStream stream, float pan);          // Set pan for audio stream (0.5 = centered)
 RLAPI void SetAudioStreamBufferSizeDefault(int size);                 // Default size for new audio streams
 
 #if defined(__cplusplus)