Skip to content

Commit

Permalink
tweak sound buffering and timing to better match pandora's refresh.
Browse files Browse the repository at this point in the history
this also changes how direct sound channels are started and
sample step precision is increased to hopefully fix gbc + direct
channel desync that has been reported on the forums.
  • Loading branch information
notaz committed Sep 7, 2011
1 parent a231964 commit 2f1c528
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 55 deletions.
7 changes: 7 additions & 0 deletions common.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@


typedef u32 fixed16_16;
typedef u32 fixed8_24;

#define float_to_fp16_16(value) \
(fixed16_16)((value) * 65536.0) \
Expand All @@ -196,6 +197,12 @@ typedef u32 fixed16_16;
#define fp16_16_fractional_part(value) \
((value) & 0xFFFF) \

#define float_to_fp8_24(value) \
(fixed8_24)((value) * 16777216.0) \

#define fp8_24_fractional_part(value) \
((value) & 0xFFFFFF) \

#define fixed_div(numerator, denominator, bits) \
(((numerator * (1 << bits)) + (denominator / 2)) / denominator) \

Expand Down
9 changes: 4 additions & 5 deletions main.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ typedef struct
u32 reload;
u32 prescale;
u32 stop_cpu_ticks;
fixed16_16 frequency_step;
fixed8_24 frequency_step;
timer_ds_channel_type direct_sound_channels;
timer_irq_type irq;
timer_status_type status;
Expand Down Expand Up @@ -132,8 +132,7 @@ static u32 prescale_table[] = { 0, 6, 8, 10 };
if(timer[timer_number].direct_sound_channels & (0x01 << channel)) \
{ \
direct_sound_channel[channel].buffer_index = \
(direct_sound_channel[channel].buffer_index + buffer_adjust) % \
BUFFER_SIZE; \
(gbc_sound_buffer_index + buffer_adjust) % BUFFER_SIZE; \
} \

#define trigger_timer(timer_number) \
Expand Down Expand Up @@ -164,8 +163,8 @@ static u32 prescale_table[] = { 0, 6, 8, 10 };
if(timer_number < 2) \
{ \
u32 buffer_adjust = \
(u32)(((float)(cpu_ticks - timer[timer_number].stop_cpu_ticks) * \
sound_frequency) / 16777216.0) * 2; \
(u32)(((float)(cpu_ticks - gbc_sound_last_cpu_ticks) * \
sound_frequency) / GBC_BASE_RATE) * 2; \
\
sound_update_frequency_step(timer_number); \
adjust_sound_buffer(timer_number, 0); \
Expand Down
64 changes: 26 additions & 38 deletions sound.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,31 +84,31 @@ void sound_timer_queue32(u32 channel, u32 value)

#define render_sample_left() \
sound_buffer[buffer_index] += current_sample + \
fp16_16_to_u32((next_sample - current_sample) * fifo_fractional) \
fp16_16_to_u32((next_sample - current_sample) * (fifo_fractional >> 8)) \

#define render_sample_right() \
sound_buffer[buffer_index + 1] += current_sample + \
fp16_16_to_u32((next_sample - current_sample) * fifo_fractional) \
fp16_16_to_u32((next_sample - current_sample) * (fifo_fractional >> 8)) \

#define render_sample_both() \
dest_sample = current_sample + \
fp16_16_to_u32((next_sample - current_sample) * fifo_fractional); \
fp16_16_to_u32((next_sample - current_sample) * (fifo_fractional >> 8)); \
sound_buffer[buffer_index] += dest_sample; \
sound_buffer[buffer_index + 1] += dest_sample \

#define render_samples(type) \
while(fifo_fractional <= 0xFFFF) \
while(fifo_fractional <= 0xFFFFFF) \
{ \
render_sample_##type(); \
fifo_fractional += frequency_step; \
buffer_index = (buffer_index + 2) % BUFFER_SIZE; \
} \

void sound_timer(fixed16_16 frequency_step, u32 channel)
void sound_timer(fixed8_24 frequency_step, u32 channel)
{
direct_sound_struct *ds = direct_sound_channel + channel;

fixed16_16 fifo_fractional = ds->fifo_fractional;
fixed8_24 fifo_fractional = ds->fifo_fractional;
u32 buffer_index = ds->buffer_index;
s16 current_sample, next_sample, dest_sample;

Expand Down Expand Up @@ -149,7 +149,7 @@ void sound_timer(fixed16_16 frequency_step, u32 channel)
}

ds->buffer_index = buffer_index;
ds->fifo_fractional = fp16_16_fractional_part(fifo_fractional);
ds->fifo_fractional = fp8_24_fractional_part(fifo_fractional);

if(((ds->fifo_top - ds->fifo_base) % 32) <= 16)
{
Expand Down Expand Up @@ -264,8 +264,8 @@ u32 gbc_sound_master_volume;
if(rate > 2048) \
rate = 2048; \
\
frequency_step = float_to_fp16_16(((131072.0 / (2048 - rate)) * 8.0) / \
sound_frequency); \
frequency_step = float_to_fp16_16(((131072.0f / (2048 - rate)) * 8.0f) \
/ sound_frequency); \
\
gs->frequency_step = frequency_step; \
gs->rate = rate; \
Expand Down Expand Up @@ -309,13 +309,6 @@ u32 gbc_sound_master_volume;

#define update_tone_noenvelope() \

#define gbc_sound_synchronize() \
while(((gbc_sound_buffer_index - sound_buffer_base) % BUFFER_SIZE) > \
(audio_buffer_size * 2)) \
{ \
SDL_CondWait(sound_cv, sound_mutex); \
} \

#define update_tone_counters(envelope_op, sweep_op) \
tick_counter += gbc_sound_tick_step; \
if(tick_counter > 0xFFFF) \
Expand Down Expand Up @@ -428,19 +421,10 @@ u32 gbc_sound_master_volume;
wave_bank[i2 + 1] = ((current_sample & 0x0F) - 8); \
} \

void synchronize_sound()
{
SDL_LockMutex(sound_mutex);

gbc_sound_synchronize();

SDL_UnlockMutex(sound_mutex);
}

void update_gbc_sound(u32 cpu_ticks)
{
fixed16_16 buffer_ticks = float_to_fp16_16(((float)(cpu_ticks -
gbc_sound_last_cpu_ticks) * sound_frequency) / 16777216.0);
fixed16_16 buffer_ticks = float_to_fp16_16((float)(cpu_ticks -
gbc_sound_last_cpu_ticks) * sound_frequency / GBC_BASE_RATE);
u32 i, i2;
gbc_sound_struct *gs = gbc_sound_channel;
fixed16_16 sample_index, frequency_step;
Expand All @@ -466,8 +450,8 @@ void update_gbc_sound(u32 cpu_ticks)
SDL_LockMutex(sound_mutex);
if(synchronize_flag)
{
if(((gbc_sound_buffer_index - sound_buffer_base) % BUFFER_SIZE) >
(audio_buffer_size * 3 / 2))
if(((gbc_sound_buffer_index - sound_buffer_base) % BUFFER_SIZE) >=
(audio_buffer_size * 2))
{
while(((gbc_sound_buffer_index - sound_buffer_base) % BUFFER_SIZE) >
(audio_buffer_size * 3 / 2))
Expand Down Expand Up @@ -705,10 +689,12 @@ void reset_sound()
gbc_sound_struct *gs = gbc_sound_channel;
u32 i;

SDL_LockMutex(sound_mutex);

sound_on = 0;
sound_buffer_base = 0;
sound_last_cpu_ticks = 0;
memset(sound_buffer, 0, audio_buffer_size);
memset(sound_buffer, 0, sizeof(sound_buffer));

for(i = 0; i < 2; i++, ds++)
{
Expand Down Expand Up @@ -736,6 +722,8 @@ void reset_sound()
gs->sample_data = square_pattern_duty[2];
gs->active_flag = 0;
}

SDL_UnlockMutex(sound_mutex);
}

void sound_exit()
Expand Down Expand Up @@ -772,14 +760,6 @@ void init_sound()
NULL
};

gbc_sound_tick_step =
float_to_fp16_16(256.0 / sound_frequency);

init_noise_table(noise_table15, 32767, 14);
init_noise_table(noise_table7, 127, 6);

reset_sound();

sound_mutex = SDL_CreateMutex();
sound_cv = SDL_CreateCond();

Expand All @@ -793,6 +773,14 @@ void init_sound()
printf("audio: freq %d, size %d\n", sound_frequency, audio_buffer_size);
#endif

gbc_sound_tick_step =
float_to_fp16_16(256.0f / sound_frequency);

init_noise_table(noise_table15, 32767, 14);
init_noise_table(noise_table7, 127, 6);

reset_sound();

SDL_PauseAudio(0);
}

Expand Down
23 changes: 11 additions & 12 deletions sound.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,14 @@

#define BUFFER_SIZE 65536

// A lot of sound cards on PC can't handle such small buffers but this
// seems to work well on PSP.

#ifdef PSP_BUILD

#define SOUND_BUFFER_SIZE 4096
#define GBA_XTAL 16777216.0f
#define GBA_60HZ_RATE 16853760.0f /* 228*(272+960)*60 */

#if !defined(PSP_BUILD) && !defined(WIZ_BUILD)
// run GBA at 60Hz (~0.5% faster) to better match host display
#define GBC_BASE_RATE GBA_60HZ_RATE
#else

#define SOUND_BUFFER_SIZE 16384

#define GBC_BASE_RATE GBA_XTAL
#endif

typedef enum
Expand All @@ -54,7 +51,7 @@ typedef struct
s8 fifo[32];
u32 fifo_base;
u32 fifo_top;
fixed16_16 fifo_fractional;
fixed8_24 fifo_fractional;
// The + 1 is to give some extra room for linear interpolation
// when wrapping around.
u32 buffer_index;
Expand Down Expand Up @@ -109,6 +106,8 @@ extern s8 square_pattern_duty[4][8];
extern u32 gbc_sound_master_volume_left;
extern u32 gbc_sound_master_volume_right;
extern u32 gbc_sound_master_volume;
extern u32 gbc_sound_buffer_index;
extern u32 gbc_sound_last_cpu_ticks;

extern u32 sound_frequency;
extern u32 sound_on;
Expand All @@ -122,7 +121,7 @@ extern SDL_mutex *sound_mutex;
void sound_timer_queue8(u32 channel, u8 value);
void sound_timer_queue16(u32 channel, u16 value);
void sound_timer_queue32(u32 channel, u32 value);
void sound_timer(fixed16_16 frequency_step, u32 channel);
void sound_timer(fixed8_24 frequency_step, u32 channel);
void sound_reset_fifo(u32 channel);
void update_gbc_sound(u32 cpu_ticks);
void init_sound();
Expand Down Expand Up @@ -320,7 +319,7 @@ static u32 gbc_sound_wave_volume[4] = { 0, 16384, 8192, 4096 };

#define sound_update_frequency_step(timer_number) \
timer[timer_number].frequency_step = \
float_to_fp16_16(16777216.0 / (timer_reload * sound_frequency)) \
float_to_fp8_24(GBC_BASE_RATE / (timer_reload * sound_frequency)) \

#endif // IN_MEMORY_C

Expand Down

0 comments on commit 2f1c528

Please sign in to comment.