From 87cc770aa62946c061e23e4db21debb865c8b5bf Mon Sep 17 00:00:00 2001 From: Samuel Walker Date: Tue, 18 Feb 2025 06:27:08 -0700 Subject: [PATCH] fIxing audio buffer --- include/audio.h | 9 ++- lib/audio.c | 190 ++++++++++++++++++++++++++++++++++-------------- 2 files changed, 140 insertions(+), 59 deletions(-) diff --git a/include/audio.h b/include/audio.h index f935dc3..20ef058 100644 --- a/include/audio.h +++ b/include/audio.h @@ -120,12 +120,13 @@ typedef struct { u8 sq1_sample_val; u64 sq1_write_index; u64 sq1_read_index; - u8 *sq1_audio_buffer; + u32 buffer_cnt; + float *sq1_audio_buffer; u8 sq2_sample_val; - u8 *sq2_audio_buffer; - u8 *ch3_audio_buffer; - u8 *ch4_audio_buffer; + float *sq2_audio_buffer; + float *ch3_audio_buffer; + float *ch4_audio_buffer; } audio_context; diff --git a/lib/audio.c b/lib/audio.c index c88a7af..3f717d5 100644 --- a/lib/audio.c +++ b/lib/audio.c @@ -6,13 +6,14 @@ #include #include #include +#include #define SAMPLE_RATE 44100.0 #define FRAMES_PER_BUFFER 64 #define TIME_PER_SAMPLE 1.0f / (SAMPLE_RATE/1000.0f/1000.0f) #define TIME_PER_AUDIO_TICK 1.0f / (1048576.0f/1000.0f/1000.0f) #define AUDIO_TICKS_PER_SAMPLE 2157281.28 / SAMPLE_RATE -#define TIME_PER_WAVE_TICK 1.0f / (2097152.0f/1000.0f/1000.0f) +#define TIME_PER_WAVE_TICK 1.0f / (2104718.0f/1000.0f/1000.0f) #define LFSR_BASE_CLOCK 262144.0f #define AUDIO_BUFFER_SIZE 102400 @@ -95,12 +96,15 @@ static int audio_callback(const void* input_uffer, void *output_buffer, float *out = (float *)output_buffer; for(int i = 0; i < framesPerBuffer; i++) { samples_occured = samples_occured + AUDIO_TICKS_PER_SAMPLE; - ctx.sq1_read_index += (int)samples_occured; - samples_occured -= (int)samples_occured; - if(ctx.sq1_read_index > ctx.sq1_write_index) { - ctx.sq1_read_index = ctx.sq1_write_index-1; - //printf("buffer underflow\n"); - return paContinue; + if(ctx.buffer_cnt < (u8)samples_occured) { + //samples_occured = samples_occured - ((int)samples_occured - ctx.buffer_cnt); + //ctx.sq1_read_index = ctx.sq1_write_index-1; + printf("buffer underflow\n"); + } else { + ctx.buffer_cnt -= (u8)samples_occured; + ctx.sq1_read_index += (u8)samples_occured; + ctx.sq1_read_index %= AUDIO_BUFFER_SIZE; + samples_occured -= (u8)samples_occured; } if(ppu_get_context()->paused) { *out++ = 0; @@ -109,34 +113,6 @@ static int audio_callback(const void* input_uffer, void *output_buffer, } float left = 0; float right = 0; - audio_time += TIME_PER_SAMPLE; - wave_time += TIME_PER_SAMPLE; - for(;audio_time >= TIME_PER_AUDIO_TICK;audio_time -= TIME_PER_AUDIO_TICK) { - //ctx.sq1_period_timer++; - ctx.sq2_period_timer++; - - //if(ctx.sq1_period_timer >= 0x800) { - // ctx.sq1_period_timer = ctx.sq1_period_reset; - // ctx.sq1_sample = (ctx.sq1_sample + 1) % 8; - //} - //if(ctx.sq2_period_timer >= 0x800) { - // ctx.sq2_period_timer = ctx.sq2_period_reset; - // ctx.sq2_sample = (ctx.sq2_sample + 1) % 8; - //} - } - for(;wave_time >= TIME_PER_WAVE_TICK;wave_time -= TIME_PER_WAVE_TICK) { - //ctx.ch3_period_timer++; - //if(ctx.ch3_period_timer >= 0x800) { - // ctx.ch3_period_timer = ctx.ch3_period_reset; - // ctx.ch3_sample = (ctx.ch3_sample + 1) % 32; - // if((ctx.ch3_sample & 0b1) == 0b1) { - // ctx.ch3_last_sample = ctx.wave_ram[ctx.ch3_sample >> 1] & 0xF; - // } else { - // ctx.ch3_last_sample = ctx.wave_ram[ctx.ch3_sample >> 1] >> 4; - // } - //} - } - float sq1_val = 0; float sq2_val = 0; float ch3_val = 0; @@ -146,7 +122,7 @@ static int audio_callback(const void* input_uffer, void *output_buffer, sq1_val = -1; if(ctx.sq1_enable) { //sq1_val = ((float)ctx.sq1_volume/15.0f) * (((float)(square_sample[ctx.sq1_duty][ctx.sq1_sample]) - 7.5f)/7.5f); - sq1_val = ((float)ctx.sq1_volume/15.0f) * (((float)(ctx.sq1_audio_buffer[ctx.sq1_read_index % AUDIO_BUFFER_SIZE]) - 7.5f)/7.5f); + sq1_val = ctx.sq1_audio_buffer[ctx.sq1_read_index]; if(ctx.ch1_left) { left += sq1_val; }else { @@ -166,7 +142,7 @@ static int audio_callback(const void* input_uffer, void *output_buffer, sq2_val = -1; if(ctx.sq2_enable) { //sq2_val = ((float)ctx.sq2_volume/15.0f) * (((float)(square_sample[ctx.sq2_duty][ctx.sq2_sample]) - 7.5f)/7.5f); - sq2_val = ((float)ctx.sq2_volume/15.0f) * (((float)(ctx.sq2_audio_buffer[ctx.sq1_read_index % AUDIO_BUFFER_SIZE]) - 7.5f)/7.5f); + sq2_val = ctx.sq2_audio_buffer[ctx.sq1_read_index];//((float)ctx.sq2_volume/15.0f) * (((float)(ctx.sq2_audio_buffer[ctx.sq1_read_index]) - 7.5f)/7.5f); if(ctx.ch2_left) { left += sq2_val; }else { @@ -186,7 +162,7 @@ static int audio_callback(const void* input_uffer, void *output_buffer, ch3_val = -1; if(ctx.ch3_enable) { //ch3_val = (((float)(ctx.ch3_last_sample >> shift) - 7.5f)/7.5f); - ch3_val = (((float)(ctx.ch3_audio_buffer[ctx.sq1_read_index % AUDIO_BUFFER_SIZE]) - 7.5f)/7.5f); + ch3_val = ctx.ch3_audio_buffer[ctx.sq1_index];//(((float)(ctx.ch3_audio_buffer[ctx.sq1_read_index]) - 7.5f)/7.5f); if(ctx.ch3_left) { left += ch3_val; //printf("left: %d\n", ctx.ch3_volume); @@ -207,7 +183,7 @@ static int audio_callback(const void* input_uffer, void *output_buffer, ch4_val = -1; if(ctx.ch4_enable) { //ch4_val = ((ctx.ch4_lfsr & 0b1) == 0b1) ? (((float)ctx.ch4_volume - 7.5f)/7.5f) : -1.0f; - ch4_val = ((float)ctx.ch4_volume/15.0f) * (((float)(ctx.ch4_audio_buffer[ctx.sq1_read_index % AUDIO_BUFFER_SIZE]) - 7.5f)/7.5f); + ch4_val = ctx.ch4_audio_buffer[ctx.sq1_read_index];//((float)ctx.ch4_volume/15.0f) * (((float)(ctx.ch4_audio_buffer[ctx.sq1_read_index]) - 7.5f)/7.5f); if(ctx.ch4_left) { left += ch4_val; //printf("left: %d\n", ctx.ch3_volume); @@ -233,6 +209,9 @@ static int audio_callback(const void* input_uffer, void *output_buffer, //left /= 4; //right /= 4; + left = ctx.sq1_audio_buffer[ctx.sq1_read_index]; + right = ctx.sq2_audio_buffer[ctx.sq1_read_index]; + bool dacs = ctx.ch1_dac || ctx.ch2_dac || ctx.ch3_dac || ctx.ch4_dac; float left_out = 0; @@ -306,10 +285,15 @@ void audio_init(){ PaStreamParameters output_parameters; PaError err; - ctx.sq1_audio_buffer = malloc(sizeof(u8) * AUDIO_BUFFER_SIZE); - ctx.sq2_audio_buffer = malloc(sizeof(u8) * AUDIO_BUFFER_SIZE); - ctx.ch3_audio_buffer = malloc(sizeof(u8) * AUDIO_BUFFER_SIZE); - ctx.ch4_audio_buffer = malloc(sizeof(u8) * AUDIO_BUFFER_SIZE); + ctx.sq1_audio_buffer = malloc(sizeof(float) * AUDIO_BUFFER_SIZE); + ctx.sq2_audio_buffer = malloc(sizeof(float) * AUDIO_BUFFER_SIZE); + ctx.ch3_audio_buffer = malloc(sizeof(float) * AUDIO_BUFFER_SIZE); + ctx.ch4_audio_buffer = malloc(sizeof(float) * AUDIO_BUFFER_SIZE); + + memset(ctx.sq1_audio_buffer, 0, sizeof(float) * AUDIO_BUFFER_SIZE); + memset(ctx.sq2_audio_buffer, 0, sizeof(float) * AUDIO_BUFFER_SIZE); + memset(ctx.ch3_audio_buffer, 0, sizeof(float) * AUDIO_BUFFER_SIZE); + memset(ctx.ch4_audio_buffer, 0, sizeof(float) * AUDIO_BUFFER_SIZE); ctx.audio_enabled = false; ctx.ch1_left = false; @@ -354,7 +338,9 @@ void audio_init(){ ctx.sq2_env_direction = false; ctx.sq2_env_pace = 0x0; ctx.sq2_env_timer = 0x0; - ctx.sq1_write_index = 1; + ctx.sq1_write_index = AUDIO_BUFFER_SIZE / 2; + ctx.sq1_read_index = 0; + ctx.buffer_cnt = AUDIO_BUFFER_SIZE / 2; err = Pa_Initialize(); if (err != paNoError) goto error; @@ -408,7 +394,7 @@ void audio_period_tick() { u32 end = get_ticks(); samples_per_sec++; if (end - start >= 1000) { - printf("Samples Per Second: %d\n", samples_per_sec); + printf("Samples In Buffer: %ld\n", ctx.buffer_cnt); start = end; samples_per_sec = 0; } @@ -458,12 +444,106 @@ void audio_period_tick() { ctx.ch4_lfsr &= ~bit_mask; } } - if(ctx.sq1_write_index < (ctx.sq1_read_index + AUDIO_BUFFER_SIZE)){ - ctx.sq1_audio_buffer[(ctx.sq1_write_index)%AUDIO_BUFFER_SIZE] = square_sample[ctx.sq1_duty][ctx.sq1_sample]; - ctx.sq2_audio_buffer[(ctx.sq1_write_index)%AUDIO_BUFFER_SIZE] = square_sample[ctx.sq2_duty][ctx.sq2_sample]; - ctx.ch3_audio_buffer[(ctx.sq1_write_index)%AUDIO_BUFFER_SIZE] = ctx.ch3_last_sample >> shift; - ctx.ch4_audio_buffer[(ctx.sq1_write_index)%AUDIO_BUFFER_SIZE] = (ctx.ch4_lfsr & 0b1) ? 0xF : 0x0; - ctx.sq1_write_index++; + + float left = 0; + float right = 0; + float sq1_val = 0; + float sq2_val = 0; + float ch3_val = 0; + float ch4_val = 0; + if(ctx.audio_enabled){ + if(ctx.ch1_dac){ + sq1_val = -1; + if(ctx.sq1_enable) { + sq1_val = ((float)ctx.sq1_volume/15.0f) * (((float)(square_sample[ctx.sq1_duty][ctx.sq1_sample]) - 7.5f)/7.5f); + if(ctx.ch1_left) { + left += sq1_val; + }else { + left -= 1; + } + if(ctx.ch1_right) { + right += sq1_val; + }else { + right -= 1; + } + } else { + left -= 1; + right -= 1; + } + } + if(ctx.ch2_dac){ + sq2_val = -1; + if(ctx.sq2_enable) { + sq2_val = ((float)ctx.sq2_volume/15.0f) * (((float)(square_sample[ctx.sq2_duty][ctx.sq2_sample]) - 7.5f)/7.5f); + if(ctx.ch2_left) { + left += sq2_val; + }else { + left -= 1; + } + if(ctx.ch2_right) { + right += sq2_val; + }else { + right -= 1; + } + } else { + left -= 1; + right -= 1; + } + } + if(ctx.ch3_dac){ + ch3_val = -1; + if(ctx.ch3_enable) { + ch3_val = (((float)(ctx.ch3_last_sample >> shift) - 7.5f)/7.5f); + if(ctx.ch3_left) { + left += ch3_val; + //printf("left: %d\n", ctx.ch3_volume); + }else { + left -= 1; + } + if(ctx.ch3_right) { + right += ch3_val; + }else { + right -= 1; + } + } else { + left -= 1; + right -= 1; + } + } + if(ctx.ch4_dac){ + ch4_val = -1; + if(ctx.ch4_enable) { + ch4_val = ((ctx.ch4_lfsr & 0b1) == 0b1) ? (((float)ctx.ch4_volume - 7.5f)/7.5f) : -1.0f; + if(ctx.ch4_left) { + left += ch4_val; + //printf("left: %d\n", ctx.ch3_volume); + }else { + left -= 1; + } + if(ctx.ch4_right) { + right += ch4_val; + } else { + right -= 1; + } + } else { + left -= 1; + right -= 1; + } + } + } + + u8 left_vol = ctx.volume_left == 0 ? 1 : ctx.volume_left; + u8 right_vol = ctx.volume_right == 0 ? 1 : ctx.volume_right; + left *= (float)left_vol/7.0f; + right *= (float)right_vol/7.0f; + + if(ctx.buffer_cnt < AUDIO_BUFFER_SIZE){ + ctx.sq1_audio_buffer[(ctx.sq1_write_index)] = left; + ctx.sq2_audio_buffer[(ctx.sq1_write_index)] = right; + //ctx.ch3_audio_buffer[(ctx.sq1_write_index)] = (((float)(ctx.ch3_last_sample >> shift)-7.5f)/7.5f); + //ctx.ch4_audio_buffer[(ctx.sq1_write_index)] = (ctx.ch4_lfsr & 0b1) ? (float)(ctx.ch4_volume-7.5f)/7.5f : -1.0f; + ctx.sq1_write_index = (ctx.sq1_write_index + 1) % AUDIO_BUFFER_SIZE; + ctx.buffer_cnt++; } else { printf("buffer overflow\n"); } @@ -1017,7 +1097,7 @@ void audio_write(u16 address, u8 value){ ctx.ch4_len = ctx.ch4_initial_len; ctx.ch4_len_fz = false; //printf("ch4 len: %02X\n", ctx.ch4_len); - printf("Write Ch4 Len: %02X\n", value); + //printf("Write Ch4 Len: %02X\n", value); } if(address == 0xFF21) { @@ -1030,7 +1110,7 @@ void audio_write(u16 address, u8 value){ } else { ctx.ch4_dac = true; } - printf("Write Ch4 env: %02X\n", value); + //printf("Write Ch4 env: %02X\n", value); } if(address == 0xFF22) { @@ -1041,7 +1121,7 @@ void audio_write(u16 address, u8 value){ float lfsr_rate = (LFSR_BASE_CLOCK) / (div * (float)(1 << ctx.ch4_clock_shift)); lfsr_clock_buffer = 1.0f / (lfsr_rate/1000.0f/1000.0f); //printf("Ch4 clock: Shift: %01X, Width: %d, Div: %f (%01X), Rate: %f, Clock %f\n", ctx.ch4_clock_shift, ctx.ch4_lfsr_width, div, ctx.ch4_clock_divider, lfsr_rate, lfsr_clock); - printf("Write Ch4 Clock: %02X\n", value); + //printf("Write Ch4 Clock: %02X\n", value); } if(address == 0xFF23) { @@ -1068,6 +1148,6 @@ void audio_write(u16 address, u8 value){ if(value & 0x80) { enable_noise(); } - printf("Write Ch4 Trigger: %02X\n", value); + //printf("Write Ch4 Trigger: %02X\n", value); } }