fIxing audio buffer

This commit is contained in:
Samuel Walker 2025-02-18 06:27:08 -07:00
parent ea91ebf5c3
commit 87cc770aa6
Signed by: piwalker
GPG Key ID: 616B1928705EA4C9
2 changed files with 140 additions and 59 deletions

View File

@ -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;

View File

@ -6,13 +6,14 @@
#include <portaudio.h>
#include <pa_ringbuffer.h>
#include <math.h>
#include <string.h>
#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);
}
}