mirror of https://github.com/LIJI32/SameBoy.git
Improve audio anti-aliasing, allow 2MHz output
This commit is contained in:
parent
ad5ca0dcf0
commit
d07b199668
53
Core/apu.c
53
Core/apu.c
|
@ -211,7 +211,7 @@ static void render(GB_gameboy_t *gb)
|
|||
}
|
||||
}
|
||||
|
||||
if (likely(gb->apu_output.last_update[i] == 0)) {
|
||||
if (likely(gb->apu_output.last_update[i] == 0 || gb->apu_output.cycles_since_render == 0)) {
|
||||
output.left += gb->apu_output.current_sample[i].left * multiplier;
|
||||
output.right += gb->apu_output.current_sample[i].right * multiplier;
|
||||
}
|
||||
|
@ -633,11 +633,14 @@ static void step_lfsr(GB_gameboy_t *gb, unsigned cycles_offset)
|
|||
|
||||
void GB_apu_run(GB_gameboy_t *gb, bool force)
|
||||
{
|
||||
uint32_t clock_rate = GB_get_clock_rate(gb) * 2;
|
||||
uint32_t clock_rate = GB_get_clock_rate(gb);
|
||||
bool orig_force = force;
|
||||
|
||||
restart:;
|
||||
uint16_t cycles = gb->apu.apu_cycles;
|
||||
|
||||
if (force ||
|
||||
(gb->apu.apu_cycles > 0x400) ||
|
||||
(cycles + gb->apu_output.cycles_since_render >= gb->apu_output.max_cycles_per_sample) ||
|
||||
(gb->apu_output.sample_cycles >= clock_rate) ||
|
||||
(gb->apu.square_sweep_calculate_countdown || gb->apu.channel_1_restart_hold || gb->apu.square_sweep_calculate_countdown_reload_timer) ||
|
||||
(gb->model <= GB_MODEL_CGB_E && (gb->apu.wave_channel.bugged_read_countdown || (gb->apu.wave_channel.enable && gb->apu.wave_channel.pulsed)))) {
|
||||
|
@ -646,9 +649,46 @@ void GB_apu_run(GB_gameboy_t *gb, bool force)
|
|||
if (!force) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Force renders to never be more than max_cycles_per_sample apart by spliting runs. */
|
||||
while (cycles + gb->apu_output.cycles_since_render > gb->apu_output.max_cycles_per_sample) {
|
||||
/* We're already past max_cycles_per_sample. This can happen when changing clock rates, etc.
|
||||
Let this sample render normally. */
|
||||
if (unlikely(gb->apu_output.cycles_since_render > gb->apu_output.max_cycles_per_sample)) break;
|
||||
|
||||
gb->apu.apu_cycles = gb->apu_output.max_cycles_per_sample - gb->apu_output.cycles_since_render;
|
||||
|
||||
if (gb->apu.apu_cycles) {
|
||||
// Run for just enough cycles to reach max_cycles_per_sample
|
||||
cycles -= gb->apu.apu_cycles;
|
||||
GB_apu_run(gb, true);
|
||||
// Re-evaluate force if needed
|
||||
if (!orig_force) {
|
||||
force = false;
|
||||
gb->apu.apu_cycles = cycles;
|
||||
goto restart;
|
||||
}
|
||||
// Check if we need another batch
|
||||
continue;
|
||||
}
|
||||
|
||||
// Render if needed
|
||||
if (gb->apu_output.sample_cycles >= clock_rate) {
|
||||
gb->apu_output.sample_cycles -= clock_rate;
|
||||
render(gb);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
gb->apu.apu_cycles = 0;
|
||||
if (!cycles) return;
|
||||
if (!cycles) {
|
||||
/* This can happen in pre-CGB stop mode */
|
||||
while (unlikely(gb->apu_output.sample_cycles >= clock_rate)) {
|
||||
gb->apu_output.sample_cycles -= clock_rate;
|
||||
render(gb);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (unlikely(gb->apu.wave_channel.bugged_read_countdown)) {
|
||||
uint16_t cycles_left = cycles;
|
||||
|
@ -1633,6 +1673,10 @@ void GB_set_sample_rate(GB_gameboy_t *gb, unsigned sample_rate)
|
|||
gb->apu_output.sample_rate = sample_rate;
|
||||
if (sample_rate) {
|
||||
gb->apu_output.highpass_rate = pow(0.999958, GB_get_clock_rate(gb) / (double)sample_rate);
|
||||
gb->apu_output.max_cycles_per_sample = ceil(GB_get_clock_rate(gb) / 2.0 / sample_rate);
|
||||
}
|
||||
else {
|
||||
gb->apu_output.max_cycles_per_sample = 0x400;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1645,6 +1689,7 @@ void GB_set_sample_rate_by_clocks(GB_gameboy_t *gb, double cycles_per_sample)
|
|||
}
|
||||
gb->apu_output.sample_rate = GB_get_clock_rate(gb) / cycles_per_sample * 2;
|
||||
gb->apu_output.highpass_rate = pow(0.999958, cycles_per_sample);
|
||||
gb->apu_output.max_cycles_per_sample = ceil(cycles_per_sample / 4);
|
||||
}
|
||||
|
||||
unsigned GB_get_sample_rate(GB_gameboy_t *gb)
|
||||
|
|
|
@ -169,6 +169,7 @@ typedef struct {
|
|||
unsigned sample_rate;
|
||||
|
||||
unsigned sample_cycles; // Counts by sample_rate until it reaches the clock frequency
|
||||
unsigned max_cycles_per_sample;
|
||||
|
||||
// Samples are NOT normalized to MAX_CH_AMP * 4 at this stage!
|
||||
unsigned cycles_since_render;
|
||||
|
|
|
@ -171,6 +171,7 @@ GB_gameboy_t *GB_init(GB_gameboy_t *gb, GB_model_t model)
|
|||
#endif
|
||||
gb->cartridge_type = &GB_cart_defs[0]; // Default cartridge type
|
||||
gb->clock_multiplier = 1.0;
|
||||
gb->apu_output.max_cycles_per_sample = 0x400;
|
||||
|
||||
if (model & GB_MODEL_NO_SFC_BIT) {
|
||||
/* Disable time syncing. Timing should be done by the SFC emulator. */
|
||||
|
|
|
@ -254,6 +254,7 @@ static void timers_run(GB_gameboy_t *gb, uint8_t cycles)
|
|||
if (GB_is_cgb(gb)) {
|
||||
gb->apu.apu_cycles += 1 << !gb->cgb_double_speed;
|
||||
}
|
||||
gb->apu_output.sample_cycles += (gb->apu_output.sample_rate << !gb->cgb_double_speed) << 1;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -267,6 +268,7 @@ static void timers_run(GB_gameboy_t *gb, uint8_t cycles)
|
|||
advance_tima_state_machine(gb);
|
||||
GB_set_internal_div_counter(gb, gb->div_counter + 4);
|
||||
gb->apu.apu_cycles += 1 << !gb->cgb_double_speed;
|
||||
gb->apu_output.sample_cycles += (gb->apu_output.sample_rate << !gb->cgb_double_speed) << 1;
|
||||
GB_SLEEP(gb, div, 2, 4);
|
||||
}
|
||||
}
|
||||
|
@ -476,7 +478,6 @@ void GB_advance_cycles(GB_gameboy_t *gb, uint8_t cycles)
|
|||
if (likely(gb->io_registers[GB_IO_LCDC] & GB_LCDC_ENABLE)) {
|
||||
gb->double_speed_alignment += cycles;
|
||||
}
|
||||
gb->apu_output.sample_cycles += cycles * gb->apu_output.sample_rate;
|
||||
gb->cycles_since_last_sync += cycles;
|
||||
gb->cycles_since_run += cycles;
|
||||
|
||||
|
|
Loading…
Reference in New Issue