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:
static int OPL_Callback(byte *stream, int len)
static uint32_t OPL_Callback(byte *buffer, uint32_t buffer_samples)
{
unsigned int filled, buffer_samples;
uint8_t *buffer = stream;
unsigned int filled;
// Repeatedly call the OPL emulator update function until the buffer is
// full.
filled = 0;
buffer_samples = len / 4;
while (filled < buffer_samples)
{
@ -196,7 +194,8 @@ static int OPL_Callback(byte *stream, int len)
AdvanceTime(nsamples);
}
return len;
return buffer_samples;
}
static void OPL_SDL_Shutdown(void)

View File

@ -52,18 +52,18 @@ static fluid_player_t *player = NULL;
static char **soundfonts;
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;
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)
{
fprintf(stderr, "Error generating FluidSynth audio\n");
fprintf(stderr, "FL_Callback: Error generating FluidSynth audio\n");
}
return len;
return buffer_samples;
}
// Load SNDFONT lump

View File

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

View File

@ -19,7 +19,7 @@
#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_SetGain(float gain);

View File

@ -198,7 +198,7 @@ typedef struct
sample_format_t sample_format;
ALenum format;
ALint byteblockalign;
ALint frame_size;
} sndfile_t;
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;
ALenum format;
ALint byteblockalign;
ALint frame_size;
file->sfdata.data = data;
file->sfdata.length = size;
@ -262,15 +262,15 @@ static boolean OpenFile(sndfile_t *file, void *data, sf_count_t size)
break;
}
byteblockalign = 1;
frame_size = 1;
if (sample_format == Int16)
{
byteblockalign = file->sfinfo.channels * 2;
frame_size = file->sfinfo.channels * 2;
}
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.
@ -301,7 +301,7 @@ static boolean OpenFile(sndfile_t *file, void *data, sf_count_t size)
file->sample_format = sample_format;
file->format = format;
file->byteblockalign = byteblockalign;
file->frame_size = frame_size;
return true;
}
@ -318,7 +318,7 @@ boolean I_SND_LoadFile(void *data, ALenum *format, byte **wavdata,
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)
{
@ -341,7 +341,7 @@ boolean I_SND_LoadFile(void *data, ALenum *format, byte **wavdata,
*wavdata = local_wavdata;
*format = file.format;
*size = num_frames * file.byteblockalign / file.sfinfo.channels;
*size = num_frames * file.frame_size / file.sfinfo.channels;
*freq = file.sfinfo.samplerate;
CloseFile(&file);
@ -352,7 +352,8 @@ boolean I_SND_LoadFile(void *data, ALenum *format, byte **wavdata,
static sndfile_t stream;
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)
{
@ -361,6 +362,7 @@ boolean I_SND_OpenStream(void *data, ALsizei size, ALenum *format, ALsizei *freq
*format = stream.format;
*freq = stream.sfinfo.samplerate;
*frame_size = stream.frame_size;
return true;
}
@ -370,10 +372,9 @@ void I_SND_SetLooping(boolean 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 frames = size / stream.byteblockalign;
if (stream.sample_format == Int16)
{
@ -389,7 +390,7 @@ int I_SND_FillStream(byte *data, ALsizei size)
sf_seek(stream.sndfile, 0, SEEK_SET);
}
return (num_frames * stream.byteblockalign);
return num_frames;
}
void I_SND_CloseStream(void)

View File

@ -25,9 +25,10 @@
boolean I_SND_LoadFile(void *data, ALenum *format, byte **wavdata,
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);
int I_SND_FillStream(byte *data, ALsizei size);
uint32_t I_SND_FillStream(byte *data, uint32_t frames);
void I_SND_CloseStream(void);
#endif