OAL stream: actually use buffer samples instead of buffer size

This was the idea from the beginning. Also reduce the buffer length to about
half a second.

* cosmetic changes
This commit is contained in:
Roman Fomin 2023-04-05 12:46:56 +07:00
parent dd536bff1b
commit 639069d399
6 changed files with 50 additions and 37 deletions

View File

@ -147,15 +147,13 @@ static void FillBuffer(uint8_t *buffer, unsigned int nsamples)
// Callback function to fill a new sound buffer: // Callback function to fill a new sound buffer:
static int OPL_Callback(byte *stream, int len) static uint32_t OPL_Callback(byte *buffer, uint32_t buffer_samples)
{ {
unsigned int filled, buffer_samples; unsigned int filled;
uint8_t *buffer = stream;
// Repeatedly call the OPL emulator update function until the buffer is // Repeatedly call the OPL emulator update function until the buffer is
// full. // full.
filled = 0; filled = 0;
buffer_samples = len / 4;
while (filled < buffer_samples) while (filled < buffer_samples)
{ {
@ -196,7 +194,8 @@ static int OPL_Callback(byte *stream, int len)
AdvanceTime(nsamples); AdvanceTime(nsamples);
} }
return len;
return buffer_samples;
} }
static void OPL_SDL_Shutdown(void) static void OPL_SDL_Shutdown(void)

View File

@ -52,18 +52,18 @@ static fluid_player_t *player = NULL;
static char **soundfonts; static char **soundfonts;
static int soundfonts_num; static int soundfonts_num;
static int FL_Callback(byte *stream, int len) static uint32_t FL_Callback(byte *buffer, uint32_t buffer_samples)
{ {
int result; int result;
result = fluid_synth_write_s16(synth, len / 4, stream, 0, 2, stream, 1, 2); result = fluid_synth_write_s16(synth, buffer_samples, buffer, 0, 2, buffer, 1, 2);
if (result != FLUID_OK) if (result != FLUID_OK)
{ {
fprintf(stderr, "Error generating FluidSynth audio\n"); fprintf(stderr, "FL_Callback: Error generating FluidSynth audio\n");
} }
return len; return buffer_samples;
} }
// Load SNDFONT lump // Load SNDFONT lump

View File

@ -28,10 +28,10 @@
#include "i_sound.h" #include "i_sound.h"
// Define the number of buffers and buffer size (in milliseconds) to use. 4 // Define the number of buffers and buffer size (in milliseconds) to use. 4
// buffers with 8192 samples each gives a nice per-chunk size, and lets the // buffers with 4096 samples each gives a nice per-chunk size, and lets the
// queue last for almost one second at 44.1khz. // queue last for about half second at 44.1khz.
#define NUM_BUFFERS 4 #define NUM_BUFFERS 4
#define BUFFER_SAMPLES 8192 #define BUFFER_SAMPLES 4096
typedef struct typedef struct
{ {
@ -44,6 +44,7 @@ typedef struct
// The format of the output stream // The format of the output stream
ALenum format; ALenum format;
ALsizei freq; ALsizei freq;
ALsizei frame_size;
} stream_player_t; } stream_player_t;
static stream_player_t player; static stream_player_t player;
@ -69,6 +70,7 @@ static boolean UpdatePlayer(void)
// Unqueue and handle each processed buffer // Unqueue and handle each processed buffer
while (processed > 0) while (processed > 0)
{ {
uint32_t frames;
ALuint bufid; ALuint bufid;
ALsizei size; ALsizei size;
@ -79,14 +81,16 @@ static boolean UpdatePlayer(void)
// the source. // the source.
if (callback) if (callback)
{ {
size = callback(player.data, BUFFER_SAMPLES); frames = callback(player.data, BUFFER_SAMPLES);
} }
else else
{ {
size = I_SND_FillStream(player.data, BUFFER_SAMPLES); frames = I_SND_FillStream(player.data, BUFFER_SAMPLES);
} }
if (size > 0)
if (frames > 0)
{ {
size = frames * player.frame_size;
alBufferData(bufid, player.format, player.data, size, player.freq); alBufferData(bufid, player.format, player.data, size, player.freq);
alSourceQueueBuffers(player.source, 1, &bufid); alSourceQueueBuffers(player.source, 1, &bufid);
} }
@ -124,7 +128,7 @@ static boolean StartPlayer(void)
{ {
int i; int i;
player.data = malloc(BUFFER_SAMPLES); player.data = malloc(BUFFER_SAMPLES * player.frame_size);
// Rewind the source position and clear the buffer queue. // Rewind the source position and clear the buffer queue.
alSourceRewind(player.source); alSourceRewind(player.source);
@ -133,23 +137,26 @@ static boolean StartPlayer(void)
// Fill the buffer queue // Fill the buffer queue
for (i = 0; i < NUM_BUFFERS; i++) for (i = 0; i < NUM_BUFFERS; i++)
{ {
uint32_t frames;
ALsizei size; ALsizei size;
// Get some data to give it to the buffer // Get some data to give it to the buffer
if (callback) if (callback)
{ {
size = callback(player.data, BUFFER_SAMPLES); frames = callback(player.data, BUFFER_SAMPLES);
} }
else else
{ {
size = I_SND_FillStream(player.data, BUFFER_SAMPLES); frames = I_SND_FillStream(player.data, BUFFER_SAMPLES);
} }
if (size < 1) if (frames < 1)
break; break;
alBufferData(player.buffers[i], player.format, player.data, size = frames * player.frame_size;
size, player.freq);
alBufferData(player.buffers[i], player.format, player.data, size,
player.freq);
} }
if (alGetError() != AL_NO_ERROR) if (alGetError() != AL_NO_ERROR)
{ {
@ -267,7 +274,11 @@ static void I_OAL_ShutdownMusic(void)
static void *I_OAL_RegisterSong(void *data, int len) static void *I_OAL_RegisterSong(void *data, int len)
{ {
if (I_SND_OpenStream(data, len, &player.format, &player.freq) == false) boolean result;
result = I_SND_OpenStream(data, len, &player.format, &player.freq,
&player.frame_size);
if (!result)
return NULL; return NULL;
StartPlayer(); StartPlayer();
@ -294,6 +305,7 @@ void I_OAL_HookMusic(callback_func_t callback_func)
player.format = AL_FORMAT_STEREO16; player.format = AL_FORMAT_STEREO16;
player.freq = SND_SAMPLERATE; player.freq = SND_SAMPLERATE;
player.frame_size = 2 * sizeof(short);
I_OAL_SetGain(1.0f); I_OAL_SetGain(1.0f);
StartPlayer(); StartPlayer();

View File

@ -19,7 +19,7 @@
#include "doomtype.h" #include "doomtype.h"
typedef int (*callback_func_t)(byte *data, int size); typedef uint32_t (*callback_func_t)(byte *buffer, uint32_t buffer_samples);
void I_OAL_HookMusic(callback_func_t callback_func); void I_OAL_HookMusic(callback_func_t callback_func);
void I_OAL_SetGain(float gain); void I_OAL_SetGain(float gain);

View File

@ -198,7 +198,7 @@ typedef struct
sample_format_t sample_format; sample_format_t sample_format;
ALenum format; ALenum format;
ALint byteblockalign; ALint frame_size;
} sndfile_t; } sndfile_t;
static void CloseFile(sndfile_t *file) static void CloseFile(sndfile_t *file)
@ -214,7 +214,7 @@ static boolean OpenFile(sndfile_t *file, void *data, sf_count_t size)
{ {
sample_format_t sample_format; sample_format_t sample_format;
ALenum format; ALenum format;
ALint byteblockalign; ALint frame_size;
file->sfdata.data = data; file->sfdata.data = data;
file->sfdata.length = size; file->sfdata.length = size;
@ -262,15 +262,15 @@ static boolean OpenFile(sndfile_t *file, void *data, sf_count_t size)
break; break;
} }
byteblockalign = 1; frame_size = 1;
if (sample_format == Int16) if (sample_format == Int16)
{ {
byteblockalign = file->sfinfo.channels * 2; frame_size = file->sfinfo.channels * 2;
} }
else if (sample_format == Float) else if (sample_format == Float)
{ {
byteblockalign = file->sfinfo.channels * 4; frame_size = file->sfinfo.channels * 4;
} }
// Figure out the OpenAL format from the file and desired sample type. // Figure out the OpenAL format from the file and desired sample type.
@ -301,7 +301,7 @@ static boolean OpenFile(sndfile_t *file, void *data, sf_count_t size)
file->sample_format = sample_format; file->sample_format = sample_format;
file->format = format; file->format = format;
file->byteblockalign = byteblockalign; file->frame_size = frame_size;
return true; return true;
} }
@ -318,7 +318,7 @@ boolean I_SND_LoadFile(void *data, ALenum *format, byte **wavdata,
return false; return false;
} }
local_wavdata = malloc(file.sfinfo.frames * file.byteblockalign / file.sfinfo.channels); local_wavdata = malloc(file.sfinfo.frames * file.frame_size / file.sfinfo.channels);
if (file.sample_format == Int16) if (file.sample_format == Int16)
{ {
@ -341,7 +341,7 @@ boolean I_SND_LoadFile(void *data, ALenum *format, byte **wavdata,
*wavdata = local_wavdata; *wavdata = local_wavdata;
*format = file.format; *format = file.format;
*size = num_frames * file.byteblockalign / file.sfinfo.channels; *size = num_frames * file.frame_size / file.sfinfo.channels;
*freq = file.sfinfo.samplerate; *freq = file.sfinfo.samplerate;
CloseFile(&file); CloseFile(&file);
@ -352,7 +352,8 @@ boolean I_SND_LoadFile(void *data, ALenum *format, byte **wavdata,
static sndfile_t stream; static sndfile_t stream;
static boolean looping; static boolean looping;
boolean I_SND_OpenStream(void *data, ALsizei size, ALenum *format, ALsizei *freq) boolean I_SND_OpenStream(void *data, ALsizei size, ALenum *format,
ALsizei *freq, ALsizei *frame_size)
{ {
if (OpenFile(&stream, data, size) == false) if (OpenFile(&stream, data, size) == false)
{ {
@ -361,6 +362,7 @@ boolean I_SND_OpenStream(void *data, ALsizei size, ALenum *format, ALsizei *freq
*format = stream.format; *format = stream.format;
*freq = stream.sfinfo.samplerate; *freq = stream.sfinfo.samplerate;
*frame_size = stream.frame_size;
return true; return true;
} }
@ -370,10 +372,9 @@ void I_SND_SetLooping(boolean on)
looping = on; looping = on;
} }
int I_SND_FillStream(byte *data, ALsizei size) uint32_t I_SND_FillStream(byte *data, uint32_t frames)
{ {
sf_count_t num_frames = 0; sf_count_t num_frames = 0;
sf_count_t frames = size / stream.byteblockalign;
if (stream.sample_format == Int16) if (stream.sample_format == Int16)
{ {
@ -389,7 +390,7 @@ int I_SND_FillStream(byte *data, ALsizei size)
sf_seek(stream.sndfile, 0, SEEK_SET); sf_seek(stream.sndfile, 0, SEEK_SET);
} }
return (num_frames * stream.byteblockalign); return num_frames;
} }
void I_SND_CloseStream(void) void I_SND_CloseStream(void)

View File

@ -25,9 +25,10 @@
boolean I_SND_LoadFile(void *data, ALenum *format, byte **wavdata, boolean I_SND_LoadFile(void *data, ALenum *format, byte **wavdata,
ALsizei *size, ALsizei *freq); ALsizei *size, ALsizei *freq);
boolean I_SND_OpenStream(void *data, ALsizei size, ALenum *format, ALsizei *freq); boolean I_SND_OpenStream(void *data, ALsizei size, ALenum *format,
ALsizei *freq, ALsizei *frame_size);
void I_SND_SetLooping(boolean on); void I_SND_SetLooping(boolean on);
int I_SND_FillStream(byte *data, ALsizei size); uint32_t I_SND_FillStream(byte *data, uint32_t frames);
void I_SND_CloseStream(void); void I_SND_CloseStream(void);
#endif #endif