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 <raysan5@gmail.com>
This commit is contained in:
parent
48a463cca8
commit
5ac07122bd
4 changed files with 76 additions and 11 deletions
|
@ -77,6 +77,9 @@ int main(void)
|
||||||
{
|
{
|
||||||
float fp = (float)(mousePosition.y);
|
float fp = (float)(mousePosition.y);
|
||||||
frequency = 40.0f + (float)(fp);
|
frequency = 40.0f + (float)(fp);
|
||||||
|
|
||||||
|
float pan = (float)(mousePosition.x) / (float)screenWidth;
|
||||||
|
SetAudioStreamPan(stream, pan);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rewrite the sine wave.
|
// Rewrite the sine wave.
|
||||||
|
@ -137,7 +140,7 @@ int main(void)
|
||||||
ClearBackground(RAYWHITE);
|
ClearBackground(RAYWHITE);
|
||||||
|
|
||||||
DrawText(TextFormat("sine frequency: %i",(int)frequency), GetScreenWidth() - 220, 10, 20, RED);
|
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
|
// Draw the current buffer state proportionate to the screen
|
||||||
for (int i = 0; i < screenWidth; i++)
|
for (int i = 0; i < screenWidth; i++)
|
||||||
|
|
70
src/raudio.c
70
src/raudio.c
|
@ -317,6 +317,7 @@ struct rAudioBuffer {
|
||||||
|
|
||||||
float volume; // Audio buffer volume
|
float volume; // Audio buffer volume
|
||||||
float pitch; // Audio buffer pitch
|
float pitch; // Audio buffer pitch
|
||||||
|
float pan; // Audio buffer pan (0 to 1)
|
||||||
|
|
||||||
bool playing; // Audio buffer state: AUDIO_PLAYING
|
bool playing; // Audio buffer state: AUDIO_PLAYING
|
||||||
bool paused; // Audio buffer state: AUDIO_PAUSED
|
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 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 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)
|
#if defined(RAUDIO_STANDALONE)
|
||||||
static bool IsFileExtension(const char *fileName, const char *ext); // Check file extension
|
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 PauseAudioBuffer(AudioBuffer *buffer);
|
||||||
void ResumeAudioBuffer(AudioBuffer *buffer);
|
void ResumeAudioBuffer(AudioBuffer *buffer);
|
||||||
void SetAudioBufferVolume(AudioBuffer *buffer, float volume);
|
void SetAudioBufferVolume(AudioBuffer *buffer, float volume);
|
||||||
|
void SetAudioBufferPan(AudioBuffer *buffer, float pan);
|
||||||
void SetAudioBufferPitch(AudioBuffer *buffer, float pitch);
|
void SetAudioBufferPitch(AudioBuffer *buffer, float pitch);
|
||||||
void TrackAudioBuffer(AudioBuffer *buffer);
|
void TrackAudioBuffer(AudioBuffer *buffer);
|
||||||
void UntrackAudioBuffer(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
|
// Init audio buffer values
|
||||||
audioBuffer->volume = 1.0f;
|
audioBuffer->volume = 1.0f;
|
||||||
audioBuffer->pitch = 1.0f;
|
audioBuffer->pitch = 1.0f;
|
||||||
|
audioBuffer->pan = 0.5f;
|
||||||
|
|
||||||
audioBuffer->playing = false;
|
audioBuffer->playing = false;
|
||||||
audioBuffer->paused = false;
|
audioBuffer->paused = false;
|
||||||
audioBuffer->looping = false;
|
audioBuffer->looping = false;
|
||||||
|
@ -641,6 +645,12 @@ void SetAudioBufferVolume(AudioBuffer *buffer, float volume)
|
||||||
if (buffer != NULL) buffer->volume = 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
|
// Set pitch for an audio buffer
|
||||||
void SetAudioBufferPitch(AudioBuffer *buffer, float pitch)
|
void SetAudioBufferPitch(AudioBuffer *buffer, float pitch)
|
||||||
{
|
{
|
||||||
|
@ -1048,6 +1058,8 @@ void PlaySoundMulti(Sound sound)
|
||||||
|
|
||||||
SetAudioBufferVolume(AUDIO.MultiChannel.pool[index], sound.stream.buffer->volume);
|
SetAudioBufferVolume(AUDIO.MultiChannel.pool[index], sound.stream.buffer->volume);
|
||||||
SetAudioBufferPitch(AUDIO.MultiChannel.pool[index], sound.stream.buffer->pitch);
|
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]->looping = sound.stream.buffer->looping;
|
||||||
AUDIO.MultiChannel.pool[index]->usage = sound.stream.buffer->usage;
|
AUDIO.MultiChannel.pool[index]->usage = sound.stream.buffer->usage;
|
||||||
AUDIO.MultiChannel.pool[index]->isSubBufferProcessed[0] = false;
|
AUDIO.MultiChannel.pool[index]->isSubBufferProcessed[0] = false;
|
||||||
|
@ -1113,6 +1125,12 @@ void SetSoundPitch(Sound sound, float pitch)
|
||||||
SetAudioBufferPitch(sound.stream.buffer, 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
|
// Convert wave data to desired format
|
||||||
void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels)
|
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);
|
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)
|
// Get music time length (in seconds)
|
||||||
float GetMusicTimeLength(Music music)
|
float GetMusicTimeLength(Music music)
|
||||||
{
|
{
|
||||||
|
@ -1989,6 +2013,14 @@ void SetAudioStreamPitch(AudioStream stream, float pitch)
|
||||||
SetAudioBufferPitch(stream.buffer, 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
|
// Default size for new audio streams
|
||||||
void SetAudioStreamBufferSizeDefault(int size)
|
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 *framesOut = (float *)pFramesOut + (framesRead*AUDIO.System.device.playback.channels);
|
||||||
float *framesIn = tempBuffer;
|
float *framesIn = tempBuffer;
|
||||||
|
|
||||||
MixAudioFrames(framesOut, framesIn, framesJustRead, audioBuffer->volume);
|
MixAudioFrames(framesOut, framesIn, framesJustRead, audioBuffer);
|
||||||
|
|
||||||
framesToRead -= framesJustRead;
|
framesToRead -= framesJustRead;
|
||||||
framesRead += 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.
|
// 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.
|
// 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)
|
||||||
{
|
{
|
||||||
|
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)
|
for (ma_uint32 iFrame = 0; iFrame < frameCount; ++iFrame)
|
||||||
{
|
{
|
||||||
for (ma_uint32 iChannel = 0; iChannel < AUDIO.System.device.playback.channels; ++iChannel)
|
frameOut[0] += (frameIn[0]*levels[0]);
|
||||||
|
frameOut[1] += (frameIn[1]*levels[1]);
|
||||||
|
frameOut += 2;
|
||||||
|
frameIn += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // pan is kinda meaningless
|
||||||
{
|
{
|
||||||
float *frameOut = framesOut + (iFrame*AUDIO.System.device.playback.channels);
|
for (ma_uint32 iFrame = 0; iFrame < frameCount; ++iFrame)
|
||||||
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,6 +155,7 @@ int GetSoundsPlaying(void); // Get number of
|
||||||
bool IsSoundPlaying(Sound sound); // Check if a sound is currently playing
|
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 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 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
|
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
|
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
|
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 ResumeMusicStream(Music music); // Resume playing paused music
|
||||||
void SeekMusicStream(Music music, float position); // Seek music to a position (in seconds)
|
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 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)
|
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 GetMusicTimeLength(Music music); // Get music time length (in seconds)
|
||||||
float GetMusicTimePlayed(Music music); // Get current music time played (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 StopAudioStream(AudioStream stream); // Stop audio stream
|
||||||
void SetAudioStreamVolume(AudioStream stream, float volume); // Set volume for audio stream (1.0 is max level)
|
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 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
|
void SetAudioStreamBufferSizeDefault(int size); // Default size for new audio streams
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -1498,6 +1498,7 @@ RLAPI void StopSoundMulti(void); // Stop an
|
||||||
RLAPI int GetSoundsPlaying(void); // Get number of sounds playing in the multichannel
|
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 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 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 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 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
|
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 ResumeMusicStream(Music music); // Resume playing paused music
|
||||||
RLAPI void SeekMusicStream(Music music, float position); // Seek music to a position (in seconds)
|
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 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 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 GetMusicTimeLength(Music music); // Get music time length (in seconds)
|
||||||
RLAPI float GetMusicTimePlayed(Music music); // Get current music time played (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 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 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 = centered)
|
||||||
RLAPI void SetAudioStreamBufferSizeDefault(int size); // Default size for new audio streams
|
RLAPI void SetAudioStreamBufferSizeDefault(int size); // Default size for new audio streams
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue