Calculate number of audio samples to read per frame deterministically
This commit is contained in:
parent
f8359a74d3
commit
20bd7c111b
|
@ -54,13 +54,9 @@ static int translation_caches_inited = 0;
|
||||||
// Usually 59.72750057 Hz, unless GBC_RATE is overclocked (for 60FPS)
|
// Usually 59.72750057 Hz, unless GBC_RATE is overclocked (for 60FPS)
|
||||||
#define GBA_FPS ((float) GBC_BASE_RATE) / (308 * 228 * 4)
|
#define GBA_FPS ((float) GBC_BASE_RATE) / (308 * 228 * 4)
|
||||||
|
|
||||||
/* An alpha factor of 1/180 is *somewhat* equivalent
|
static s16 *audio_sample_buffer = NULL;
|
||||||
* to calculating the average for the last 180
|
static float audio_samples_per_frame = 0.0f;
|
||||||
* frames, or 3 seconds of runtime... */
|
static float audio_samples_accumulator = 0.0f;
|
||||||
#define SAMPLES_PER_FRAME_MOVING_AVG_ALPHA (1.0f / 180.0f)
|
|
||||||
static s16 *audio_sample_buffer = NULL;
|
|
||||||
static u32 audio_sample_buffer_size = 0;
|
|
||||||
static float audio_samples_per_frame_avg = 0.0f;
|
|
||||||
|
|
||||||
/* Workaround for a RetroArch audio driver
|
/* Workaround for a RetroArch audio driver
|
||||||
* limitation: a maximum of 1024 frames
|
* limitation: a maximum of 1024 frames
|
||||||
|
@ -383,51 +379,40 @@ void set_fastforward_override(bool fastforward)
|
||||||
|
|
||||||
static void audio_run(void)
|
static void audio_run(void)
|
||||||
{
|
{
|
||||||
u32 samples_available = sound_samples_available();
|
s16 *audio_buffer_ptr;
|
||||||
|
u32 samples_to_read;
|
||||||
|
u32 samples_produced;
|
||||||
|
|
||||||
if (samples_available > 0)
|
/* audio_samples_per_frame is decimal;
|
||||||
|
* get integer component */
|
||||||
|
samples_to_read = (u32)audio_samples_per_frame;
|
||||||
|
|
||||||
|
/* Account for fractional component */
|
||||||
|
audio_samples_accumulator += audio_samples_per_frame -
|
||||||
|
(float)samples_to_read;
|
||||||
|
|
||||||
|
if (audio_samples_accumulator >= 1.0f)
|
||||||
{
|
{
|
||||||
s16 *audio_buffer_ptr;
|
samples_to_read++;
|
||||||
u32 samples_to_read;
|
audio_samples_accumulator -= 1.0f;
|
||||||
u32 samples_produced;
|
}
|
||||||
|
|
||||||
/* Update 'running average' of number of
|
samples_produced = sound_read_samples(audio_sample_buffer, samples_to_read);
|
||||||
* samples per frame.
|
|
||||||
* Note that this is not a true running
|
|
||||||
* average, but just a leaky-integrator/
|
|
||||||
* exponential moving average, used because
|
|
||||||
* it is simple and fast (i.e. requires no
|
|
||||||
* window of samples). */
|
|
||||||
audio_samples_per_frame_avg = (SAMPLES_PER_FRAME_MOVING_AVG_ALPHA * (float)samples_available) +
|
|
||||||
((1.0f - SAMPLES_PER_FRAME_MOVING_AVG_ALPHA) * audio_samples_per_frame_avg);
|
|
||||||
|
|
||||||
samples_to_read = (u32)(audio_samples_per_frame_avg + 0.5f);
|
/* Workaround for a RetroArch audio driver
|
||||||
|
* limitation: a maximum of 1024 frames
|
||||||
|
* can be written per call of audio_batch_cb(),
|
||||||
|
* so we have to send samples in chunks */
|
||||||
|
audio_buffer_ptr = audio_sample_buffer;
|
||||||
|
while (samples_produced > 0)
|
||||||
|
{
|
||||||
|
u32 samples_to_write = (samples_produced > AUDIO_BATCH_FRAMES_MAX) ?
|
||||||
|
AUDIO_BATCH_FRAMES_MAX : samples_produced;
|
||||||
|
|
||||||
/* Resize audio output buffer, if required */
|
audio_batch_cb(audio_buffer_ptr, samples_to_write);
|
||||||
if (audio_sample_buffer_size < (samples_to_read * 2))
|
|
||||||
{
|
|
||||||
audio_sample_buffer_size = (samples_to_read * 2);
|
|
||||||
audio_sample_buffer = (s16*)realloc(audio_sample_buffer,
|
|
||||||
audio_sample_buffer_size * sizeof(s16));
|
|
||||||
}
|
|
||||||
|
|
||||||
samples_produced = sound_read_samples(audio_sample_buffer, samples_to_read);
|
samples_produced -= samples_to_write;
|
||||||
|
audio_buffer_ptr += samples_to_write << 1;
|
||||||
/* Workaround for a RetroArch audio driver
|
|
||||||
* limitation: a maximum of 1024 frames
|
|
||||||
* can be written per call of audio_batch_cb(),
|
|
||||||
* so we have to send samples in chunks */
|
|
||||||
audio_buffer_ptr = audio_sample_buffer;
|
|
||||||
while (samples_produced > 0)
|
|
||||||
{
|
|
||||||
u32 samples_to_write = (samples_produced > AUDIO_BATCH_FRAMES_MAX) ?
|
|
||||||
AUDIO_BATCH_FRAMES_MAX : samples_produced;
|
|
||||||
|
|
||||||
audio_batch_cb(audio_buffer_ptr, samples_to_write);
|
|
||||||
|
|
||||||
samples_produced -= samples_to_write;
|
|
||||||
audio_buffer_ptr += samples_to_write << 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -521,10 +506,11 @@ void retro_get_system_av_info(struct retro_system_av_info* info)
|
||||||
|
|
||||||
void retro_init(void)
|
void retro_init(void)
|
||||||
{
|
{
|
||||||
u32 audio_samples_per_frame = (u32)((float)(GBA_SOUND_FREQUENCY) / (float)(GBA_FPS));
|
u32 audio_sample_buffer_size;
|
||||||
audio_sample_buffer_size = audio_samples_per_frame * 2;
|
audio_samples_per_frame = (float)(GBA_SOUND_FREQUENCY) / (float)(GBA_FPS);
|
||||||
audio_sample_buffer = (s16*)malloc(audio_sample_buffer_size * sizeof(s16));
|
audio_samples_accumulator = 0.0f;
|
||||||
audio_samples_per_frame_avg = (float)audio_samples_per_frame;
|
audio_sample_buffer_size = ((u32)audio_samples_per_frame + 1) * 2;
|
||||||
|
audio_sample_buffer = (s16*)malloc(audio_sample_buffer_size * sizeof(s16));
|
||||||
|
|
||||||
#if defined(HAVE_DYNAREC)
|
#if defined(HAVE_DYNAREC)
|
||||||
#if defined(MMAP_JIT_CACHE)
|
#if defined(MMAP_JIT_CACHE)
|
||||||
|
@ -666,9 +652,9 @@ void retro_deinit(void)
|
||||||
if (audio_sample_buffer)
|
if (audio_sample_buffer)
|
||||||
free(audio_sample_buffer);
|
free(audio_sample_buffer);
|
||||||
|
|
||||||
audio_sample_buffer = NULL;
|
audio_sample_buffer = NULL;
|
||||||
audio_sample_buffer_size = 0;
|
audio_samples_per_frame = 0.0f;
|
||||||
audio_samples_per_frame_avg = 0.0f;
|
audio_samples_accumulator = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
static retro_time_t retro_perf_dummy_get_time_usec() { return 0; }
|
static retro_time_t retro_perf_dummy_get_time_usec() { return 0; }
|
||||||
|
|
29
sound.c
29
sound.c
|
@ -749,22 +749,22 @@ unsigned sound_write_savestate(u8 *dst)
|
||||||
return (unsigned int)(dst - startp);
|
return (unsigned int)(dst - startp);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 sound_samples_available(void)
|
u32 sound_read_samples(s16 *out, u32 frames)
|
||||||
{
|
{
|
||||||
u32 num_samples = (gbc_sound_buffer_index - sound_buffer_base) & BUFFER_SIZE_MASK;
|
|
||||||
num_samples = (num_samples > 512) ? (num_samples - 512) : 0;
|
|
||||||
return (num_samples >> 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 sound_read_samples(s16 *out, u32 count)
|
|
||||||
{
|
|
||||||
u32 samples_available = sound_samples_available();
|
|
||||||
u32 i;
|
u32 i;
|
||||||
|
u32 samples_to_read = frames << 1;
|
||||||
|
/* Get total number of samples in the buffer */
|
||||||
|
u32 samples_available = (gbc_sound_buffer_index - sound_buffer_base) & BUFFER_SIZE_MASK;
|
||||||
|
/* The last 512 samples are 'in use', and cannot
|
||||||
|
* be read out yet */
|
||||||
|
samples_available = (samples_available > 512) ? (samples_available - 512) : 0;
|
||||||
|
/* Available sample count must be an even number */
|
||||||
|
samples_available = (samples_available >> 1) << 1;
|
||||||
|
|
||||||
if (count > samples_available)
|
if (samples_to_read > samples_available)
|
||||||
count = samples_available;
|
samples_to_read = samples_available;
|
||||||
|
|
||||||
for(i = 0; i < (count << 1); i++)
|
for(i = 0; i < samples_to_read; i++)
|
||||||
{
|
{
|
||||||
u32 source_index = (sound_buffer_base + i) & BUFFER_SIZE_MASK;
|
u32 source_index = (sound_buffer_base + i) & BUFFER_SIZE_MASK;
|
||||||
s32 current_sample = sound_buffer[source_index];
|
s32 current_sample = sound_buffer[source_index];
|
||||||
|
@ -779,8 +779,9 @@ u32 sound_read_samples(s16 *out, u32 count)
|
||||||
out[i] = current_sample * 16;
|
out[i] = current_sample * 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
sound_buffer_base += (count << 1);
|
sound_buffer_base += samples_to_read;
|
||||||
sound_buffer_base &= BUFFER_SIZE_MASK;
|
sound_buffer_base &= BUFFER_SIZE_MASK;
|
||||||
|
|
||||||
return count;
|
/* Function returns number of frames read */
|
||||||
|
return (samples_to_read >> 1);
|
||||||
}
|
}
|
||||||
|
|
3
sound.h
3
sound.h
|
@ -108,8 +108,7 @@ void init_sound(int need_reset);
|
||||||
unsigned sound_write_savestate(u8 *dst);
|
unsigned sound_write_savestate(u8 *dst);
|
||||||
bool sound_read_savestate(const u8 *src);
|
bool sound_read_savestate(const u8 *src);
|
||||||
|
|
||||||
u32 sound_samples_available(void);
|
u32 sound_read_samples(s16 *out, u32 frames);
|
||||||
u32 sound_read_samples(s16 *out, u32 count);
|
|
||||||
|
|
||||||
void reset_sound(void);
|
void reset_sound(void);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue