THIS COMMIT IS FOR REVIEW: audio update functions clarity review in examples

This commit is contained in:
iann 2025-11-13 07:31:47 +09:00
parent 79a6188e9c
commit b3c25186d9
5 changed files with 125 additions and 89 deletions

View File

@ -4,7 +4,7 @@
*
* Example complexity rating: [] 3/4
*
* Example originally created with raylib 1.6, last time updated with raylib 4.2
* Example originally created with raylib 1.6, last time updated with raylib 6.0
*
* Example created by Ramon Santamaria (@raysan5) and reviewed by James Hofmann (@triplefox)
*
@ -24,34 +24,6 @@
#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;
// Audio input processing callback
void AudioInputCallback(void *buffer, unsigned int frames)
{
audioFrequency = frequency + (audioFrequency - frequency)*0.95f;
float incr = audioFrequency/44100.0f;
short *d = (short *)buffer;
for (unsigned int i = 0; i < frames; i++)
{
d[i] = (short)(32000.0f*sinf(2*PI*sineIdx));
sineIdx += incr;
if (sineIdx > 1.0f) sineIdx -= 1.0f;
}
}
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
@ -71,8 +43,6 @@ int main(void)
// Init raw audio stream (sample rate: 44100, sample size: 16bit-short, channels: 1-mono)
AudioStream stream = LoadAudioStream(44100, 16, 1);
SetAudioStreamCallback(stream, AudioInputCallback);
// Buffer for the single cycle waveform we are synthesizing
short *data = (short *)malloc(sizeof(short)*MAX_SAMPLES);
@ -84,7 +54,6 @@ int main(void)
// Position read in to determine next frequency
Vector2 mousePosition = { -100.0f, -100.0f };
/*
// Cycles per second (hz)
float frequency = 440.0f;
@ -93,7 +62,6 @@ 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;
@ -124,8 +92,8 @@ int main(void)
if (frequency != oldFrequency)
{
// Compute wavelength. Limit size in both directions
//int oldWavelength = waveLength;
waveLength = (int)(22050/frequency);
int oldWavelength = waveLength;
waveLength = (int)(stream.sampleRate/frequency);
if (waveLength > MAX_SAMPLES/2) waveLength = MAX_SAMPLES/2;
if (waveLength < 1) waveLength = 1;
@ -141,11 +109,10 @@ int main(void)
}
// 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))
{
@ -174,7 +141,6 @@ int main(void)
// Copy finished frame to audio stream
UpdateAudioStream(stream, writeBuf, MAX_SAMPLES_PER_UPDATE);
}
*/
//----------------------------------------------------------------------------------
// Draw

View File

@ -4,7 +4,7 @@
*
* Example complexity rating: [] 3/4
*
* Example originally created with raylib 1.6, last time updated with raylib 4.2
* Example originally created with raylib 1.6, last time updated with raylib 6.0
*
* Example created by Ramon Santamaria (@raysan5) and reviewed by James Hofmann (@triplefox)
*
@ -19,7 +19,12 @@
#include <stdlib.h> // Required for: malloc(), free()
#include <math.h> // Required for: sinf()
#include <string.h> // Required for: memcpy()
enum Flags { FLAG_CHANNEL_MONO = 1u<<0, FLAG_SAMPLESIZE_SHORT = 1u<<1 };
static unsigned int gflags = FLAG_CHANNEL_MONO | FLAG_SAMPLESIZE_SHORT; // mono + 16-bit to match initial stream specs
#define CHANNEL_MONO() ((gflags & FLAG_CHANNEL_MONO) != 0)
#define SAMPLESIZE_SHORT() ((gflags & FLAG_SAMPLESIZE_SHORT) != 0)
#define TOGGLE(K, F) do { if (IsKeyPressed(K)) { gflags ^= (F); } } while (0)
#define MAX_SAMPLES 512
#define MAX_SAMPLES_PER_UPDATE 4096
@ -37,7 +42,7 @@ float oldFrequency = 1.0f;
float sineIdx = 0.0f;
// Audio input processing callback
void AudioInputCallback(void *buffer, unsigned int frames)
void AudioInputCallbackMonoShort(void *buffer, unsigned int frames)
{
audioFrequency = frequency + (audioFrequency - frequency)*0.95f;
@ -52,6 +57,54 @@ void AudioInputCallback(void *buffer, unsigned int frames)
}
}
void AudioInputCallbackStereoShort(void *buffer, unsigned int frames)
{
audioFrequency = frequency + (audioFrequency - frequency)*0.95f;
float incr = audioFrequency/44100.0f;
short *d = (short *)buffer;
for (unsigned int i = 0; i < frames; i++)
{
short s = (short)(32000.0f*sinf(2*PI*sineIdx));
d[2*i + 0] = s; // L
d[2*i + 1] = s; // R
sineIdx += incr;
if (sineIdx > 1.0f) sineIdx -= 1.0f;
}
}
void AudioInputCallbackMonoFloat(void *buffer, unsigned int frames)
{
audioFrequency = frequency + (audioFrequency - frequency)*0.95f;
float incr = audioFrequency/44100.0f;
float *d = (float *)buffer;
for (unsigned int i = 0; i < frames; i++)
{
d[i] = sinf(2*PI*sineIdx);
sineIdx += incr;
if (sineIdx > 1.0f) sineIdx -= 1.0f;
}
}
void AudioInputCallbackStereoFloat(void *buffer, unsigned int frames)
{
audioFrequency = frequency + (audioFrequency - frequency)*0.95f;
float incr = audioFrequency/44100.0f;
float *d = (float *)buffer;
for (unsigned int i = 0; i < frames; i++)
{
float s = sinf(2*PI*sineIdx);
d[2*i + 0] = s;
d[2*i + 1] = s;
sineIdx += incr;
if (sineIdx > 1.0f) sineIdx -= 1.0f;
}
}
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
@ -62,7 +115,7 @@ int main(void)
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [audio] example - raw stream");
InitWindow(screenWidth, screenHeight, "raylib [audio] example - raw stream with callbacks");
InitAudioDevice(); // Initialize audio device
@ -71,7 +124,9 @@ int main(void)
// Init raw audio stream (sample rate: 44100, sample size: 16bit-short, channels: 1-mono)
AudioStream stream = LoadAudioStream(44100, 16, 1);
SetAudioStreamCallback(stream, AudioInputCallback);
SetAudioStreamCallback(stream, AudioInputCallbackMonoShort);
unsigned int previousSampleSize = stream.sampleSize;
unsigned int previousChannels = stream.channels;
// Buffer for the single cycle waveform we are synthesizing
short *data = (short *)malloc(sizeof(short)*MAX_SAMPLES);
@ -84,17 +139,6 @@ int main(void)
// Position read in to determine next frequency
Vector2 mousePosition = { -100.0f, -100.0f };
/*
// Cycles per second (hz)
float frequency = 440.0f;
// Previous value, used to test if sine needs to be rewritten, and to smoothly modulate frequency
float oldFrequency = 1.0f;
// 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;
@ -106,6 +150,32 @@ int main(void)
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
TOGGLE(KEY_M, FLAG_CHANNEL_MONO);
TOGGLE(KEY_F, FLAG_SAMPLESIZE_SHORT);
unsigned int nextSampleSize = (SAMPLESIZE_SHORT())? 16u : 32u;
unsigned int nextChannels = (CHANNEL_MONO())? 1u : 2u;
if (nextSampleSize != previousSampleSize || nextChannels != previousChannels)
{
StopAudioStream(stream);
UnloadAudioStream(stream);
stream = LoadAudioStream(44100, nextSampleSize, nextChannels);
// CORRECT ALIGNMENT
if (nextChannels == 1 && nextSampleSize == 16) SetAudioStreamCallback(stream, AudioInputCallbackMonoShort);
if (nextChannels == 2 && nextSampleSize == 16) SetAudioStreamCallback(stream, AudioInputCallbackStereoShort);
if (nextChannels == 1 && nextSampleSize == 32) SetAudioStreamCallback(stream, AudioInputCallbackMonoFloat);
if (nextChannels == 2 && nextSampleSize == 32) SetAudioStreamCallback(stream, AudioInputCallbackStereoFloat);
// INCORRECT ALIGNMENT TESTS: comment and uncomment or add your own to observe common misconfigurations
// if (nextChannels == 1 && nextSampleSize == 16) SetAudioStreamCallback(stream, AudioInputCallbackStereoShort);
// if (nextChannels == 1 && nextSampleSize == 32) SetAudioStreamCallback(stream, AudioInputCallbackMonoShort);
// if (nextChannels == 2 && nextSampleSize == 32) SetAudioStreamCallback(stream, AudioInputCallbackMonoShort);
// if (nextChannels == 2 && nextSampleSize == 16) SetAudioStreamCallback(stream, AudioInputCallbackMonoFloat);
// if (nextChannels == 2 && nextSampleSize == 16) SetAudioStreamCallback(stream, AudioInputCallbackStereoFloat);
PlayAudioStream(stream);
previousSampleSize = nextSampleSize;
previousChannels = nextChannels;
}
// Update
//----------------------------------------------------------------------------------
mousePosition = GetMousePosition();
@ -124,7 +194,6 @@ int main(void)
if (frequency != oldFrequency)
{
// Compute wavelength. Limit size in both directions
//int oldWavelength = waveLength;
waveLength = (int)(22050/frequency);
if (waveLength > MAX_SAMPLES/2) waveLength = MAX_SAMPLES/2;
if (waveLength < 1) waveLength = 1;
@ -140,41 +209,9 @@ int main(void)
data[j] = (short)0;
}
// Scale read cursor's position to minimize transition artifacts
//readCursor = (int)(readCursor*((float)waveLength/(float)oldWavelength));
oldFrequency = frequency;
}
/*
// Refill audio stream if required
if (IsAudioStreamProcessed(stream))
{
// Synthesize a buffer that is exactly the requested size
int writeCursor = 0;
while (writeCursor < MAX_SAMPLES_PER_UPDATE)
{
// Start by trying to write the whole chunk at once
int writeLength = MAX_SAMPLES_PER_UPDATE-writeCursor;
// Limit to the maximum readable size
int readLength = waveLength-readCursor;
if (writeLength > readLength) writeLength = readLength;
// Write the slice
memcpy(writeBuf + writeCursor, data + readCursor, writeLength*sizeof(short));
// Update cursors and loop audio
readCursor = (readCursor + writeLength) % waveLength;
writeCursor += writeLength;
}
// Copy finished frame to audio stream
UpdateAudioStream(stream, writeBuf, MAX_SAMPLES_PER_UPDATE);
}
*/
//----------------------------------------------------------------------------------
// Draw
@ -185,6 +222,10 @@ int main(void)
DrawText(TextFormat("sine frequency: %i",(int)frequency), GetScreenWidth() - 220, 10, 20, RED);
DrawText("click mouse button to change frequency or pan", 10, 10, 20, DARKGRAY);
DrawText("press M to SWAP channels [ M ]:", 250, 366, 20, BLUE);
DrawText((CHANNEL_MONO())? "MONO" : "STEREO", 600, 366, 20, (CHANNEL_MONO())? GREEN : RED);
DrawText("press F to SWAP Sample Size [ F ]:", 250, 400, 20, BLUE);
DrawText((SAMPLESIZE_SHORT())? "16" : "32", 620, 400, 20, (SAMPLESIZE_SHORT())? GREEN : RED);
// Draw the current buffer state proportionate to the screen
for (int i = 0; i < screenWidth; i++)

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -4,7 +4,7 @@
*
* Example complexity rating: [] 1/4
*
* Example originally created with raylib 1.1, last time updated with raylib 3.5
* Example originally created with raylib 1.1, last time updated with raylib 6.0
*
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software
@ -14,6 +14,8 @@
********************************************************************************************/
#include "raylib.h"
#include <stdlib.h> // Required for: malloc(), free()
#include <string.h> // Required for: memcpy()
//------------------------------------------------------------------------------------
// Program main entry point
@ -32,6 +34,17 @@ int main(void)
Sound fxWav = LoadSound("resources/sound.wav"); // Load WAV audio file
Sound fxOgg = LoadSound("resources/target.ogg"); // Load OGG audio file
bool soundReversed = false;
float *soundData = malloc(sizeof(float)*fxWav.frameCount*fxWav.stream.channels);
float *scratchSoundData = malloc(sizeof(float)*fxWav.frameCount*fxWav.stream.channels);
Wave wave = LoadWave("resources/sound.wav");
// Sounds always have 32bit sampleSize:
WaveFormat(&wave, fxWav.stream.sampleRate, 32, fxWav.stream.channels);
memcpy(soundData, wave.data, sizeof(float)*fxWav.frameCount*fxWav.stream.channels);
UnloadWave(wave);
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
@ -40,6 +53,18 @@ int main(void)
{
// Update
//----------------------------------------------------------------------------------
if (IsKeyPressed(KEY_R))
{
soundReversed = !soundReversed;
for (unsigned int i = 0; i < fxWav.frameCount; i++)
{
unsigned int src = (soundReversed)? fxWav.frameCount - 1 - i : i;
// Sounds always have STEREO channels:
scratchSoundData[i * fxWav.stream.channels + 0] = soundData[src * fxWav.stream.channels + 0];
scratchSoundData[i * fxWav.stream.channels + 1] = soundData[src * fxWav.stream.channels + 1];
}
UpdateSound(fxWav, scratchSoundData, fxWav.frameCount);
}
if (IsKeyPressed(KEY_SPACE)) PlaySound(fxWav); // Play WAV sound
if (IsKeyPressed(KEY_ENTER)) PlaySound(fxOgg); // Play OGG sound
//----------------------------------------------------------------------------------
@ -51,7 +76,9 @@ int main(void)
ClearBackground(RAYWHITE);
DrawText("Press SPACE to PLAY the WAV sound!", 200, 180, 20, LIGHTGRAY);
DrawText("Press ENTER to PLAY the OGG sound!", 200, 220, 20, LIGHTGRAY);
DrawText(TextFormat("Press R to REVERSE the WAV sound : "), 120, 220, 20, LIGHTGRAY);
DrawText((soundReversed)? "BACKWARDS" : "FORWARDS", 525, 220, 20, (soundReversed)? MAROON : DARKGREEN);
DrawText("Press ENTER to PLAY the OGG sound!", 200, 260, 20, LIGHTGRAY);
EndDrawing();
//----------------------------------------------------------------------------------
@ -59,6 +86,8 @@ int main(void)
// De-Initialization
//--------------------------------------------------------------------------------------
free(soundData);
free(scratchSoundData);
UnloadSound(fxWav); // Unload sound data
UnloadSound(fxOgg); // Unload sound data

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 16 KiB