Fixed audio buffer popping
This commit is contained in:
parent
8e5c3234ef
commit
a094e5123b
@ -134,6 +134,7 @@ void audio_init();
|
||||
void audio_tick();
|
||||
void audio_period_tick();
|
||||
void lfsr_tick();
|
||||
void audio_sample_tick();
|
||||
|
||||
u8 audio_read(u16 address);
|
||||
void audio_write(u16 address, u8 value);
|
||||
|
183
lib/audio.c
183
lib/audio.c
@ -12,10 +12,11 @@
|
||||
#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 AUDIO_TICKS_PER_SAMPLE 4194304.0 / SAMPLE_RATE
|
||||
#define SAMPLES_PER_AUDIO_TICK SAMPLE_RATE / 4194304.0
|
||||
#define TIME_PER_WAVE_TICK 1.0f / (2104718.0f/1000.0f/1000.0f)
|
||||
#define LFSR_BASE_CLOCK 262144.0f
|
||||
#define AUDIO_BUFFER_SIZE (int)(SAMPLE_RATE / 10)
|
||||
#define AUDIO_BUFFER_SIZE FRAMES_PER_BUFFER
|
||||
|
||||
static audio_context ctx;
|
||||
|
||||
@ -103,14 +104,17 @@ static int audio_callback(const void* input_uffer, void *output_buffer,
|
||||
//}
|
||||
for(int i = 0; i < framesPerBuffer; i++) {
|
||||
//samples_occured = samples_occured + AUDIO_TICKS_PER_SAMPLE-1;
|
||||
while(ctx.buffer_cnt == 0) {
|
||||
delay(1);
|
||||
}
|
||||
//while(ctx.buffer_cnt == 0) {
|
||||
// delay(1);
|
||||
//}
|
||||
if(ctx.buffer_cnt == 0) {
|
||||
//samples_occured = samples_occured - ((int)samples_occured - ctx.buffer_cnt);
|
||||
//ctx.sq1_read_index = ctx.sq1_write_index-1;
|
||||
//printf("buffer underflow\n");
|
||||
return paContinue;
|
||||
continue;
|
||||
//ctx.buffer_cnt++;
|
||||
//ctx.sq1_read_index--;
|
||||
//ctx.sq1_read_index %= AUDIO_BUFFER_SIZE;
|
||||
} else {
|
||||
//ctx.buffer_cnt -= (u8)samples_occured;
|
||||
//ctx.sq1_read_index += (u8)samples_occured;
|
||||
@ -218,9 +222,6 @@ static int audio_callback(const void* input_uffer, void *output_buffer,
|
||||
left *= (float)left_vol/7.0f;
|
||||
right *= (float)right_vol/7.0f;
|
||||
|
||||
//left /= 4;
|
||||
//right /= 4;
|
||||
|
||||
left = ctx.sq1_audio_buffer[ctx.sq1_read_index];
|
||||
right = ctx.sq2_audio_buffer[ctx.sq1_read_index];
|
||||
ctx.sq1_read_index++;
|
||||
@ -233,8 +234,8 @@ static int audio_callback(const void* input_uffer, void *output_buffer,
|
||||
if(dacs) {
|
||||
left_out = left - left_cap;
|
||||
right_out = right - right_cap;
|
||||
left_cap = left - left_out * 0.996f;
|
||||
right_cap = right - right_out * 0.996f;
|
||||
left_cap = left - left_out * 0.999958f;
|
||||
right_cap = right - right_out * 0.999958f;
|
||||
}
|
||||
|
||||
|
||||
@ -333,9 +334,9 @@ void audio_init(){
|
||||
ctx.sq2_env_direction = false;
|
||||
ctx.sq2_env_pace = 0x0;
|
||||
ctx.sq2_env_timer = 0x0;
|
||||
ctx.sq1_write_index = 0;
|
||||
ctx.sq1_write_index = AUDIO_BUFFER_SIZE - 1;
|
||||
ctx.sq1_read_index = 0;
|
||||
ctx.buffer_cnt = 0;
|
||||
ctx.buffer_cnt = AUDIO_BUFFER_SIZE - 1;
|
||||
|
||||
err = Pa_Initialize();
|
||||
if (err != paNoError) goto error;
|
||||
@ -345,7 +346,7 @@ void audio_init(){
|
||||
goto error;
|
||||
}
|
||||
output_parameters.channelCount = 2;
|
||||
output_parameters.sampleFormat = paFloat32;
|
||||
output_parameters.sampleFormat = paFloat32 | paNonInterleaved;
|
||||
output_parameters.suggestedLatency = Pa_GetDeviceInfo(output_parameters.device)->defaultLowOutputLatency;
|
||||
output_parameters.hostApiSpecificStreamInfo = NULL;
|
||||
printf("default sample rate: %lf\n", Pa_GetDeviceInfo(output_parameters.device)->defaultSampleRate);
|
||||
@ -354,9 +355,9 @@ void audio_init(){
|
||||
NULL,
|
||||
&output_parameters,
|
||||
SAMPLE_RATE,
|
||||
paFramesPerBufferUnspecified,
|
||||
FRAMES_PER_BUFFER,
|
||||
paNoFlag,
|
||||
audio_callback,
|
||||
NULL,
|
||||
&ctx);
|
||||
if(err != paNoError) goto error;
|
||||
err = Pa_StartStream(stream);
|
||||
@ -399,51 +400,10 @@ void lfsr_tick() {
|
||||
}
|
||||
}
|
||||
|
||||
static double cycles_needed = 0;
|
||||
|
||||
void audio_period_tick() {
|
||||
period_tick++;
|
||||
u32 end = get_ticks();
|
||||
samples_per_sec++;
|
||||
if (end - start >= 1000) {
|
||||
printf("Samples In Buffer: %ld\n", ctx.buffer_cnt);
|
||||
start = end;
|
||||
samples_per_sec = 0;
|
||||
}
|
||||
if(period_tick % 2 == 0){
|
||||
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;
|
||||
}
|
||||
}
|
||||
u8 shift = 0;
|
||||
if(ctx.ch3_volume == 0b10) {
|
||||
shift = 1;
|
||||
}
|
||||
if(ctx.ch3_volume == 0b00) {
|
||||
shift = 4;
|
||||
}
|
||||
if(ctx.ch3_volume == 0b11) {
|
||||
shift = 2;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void audio_sample_tick() {
|
||||
lfsr_tick();
|
||||
float left = 0;
|
||||
float right = 0;
|
||||
float sq1_val = 0;
|
||||
@ -490,6 +450,16 @@ void audio_period_tick() {
|
||||
}
|
||||
}
|
||||
if(ctx.ch3_dac){
|
||||
u8 shift = 0;
|
||||
if(ctx.ch3_volume == 0b10) {
|
||||
shift = 1;
|
||||
}
|
||||
if(ctx.ch3_volume == 0b00) {
|
||||
shift = 4;
|
||||
}
|
||||
if(ctx.ch3_volume == 0b11) {
|
||||
shift = 2;
|
||||
}
|
||||
ch3_val = -1;
|
||||
if(ctx.ch3_enable) {
|
||||
ch3_val = (((float)(ctx.ch3_last_sample >> shift) - 7.5f)/7.5f);
|
||||
@ -557,25 +527,100 @@ void audio_period_tick() {
|
||||
ctx.ch4_index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
smooth_left = smooth_left - (LPF_Beta * (smooth_left - left));
|
||||
smooth_right = smooth_right - (LPF_Beta * (smooth_right - right));
|
||||
|
||||
if((period_tick % (int)(AUDIO_TICKS_PER_SAMPLE)) == 0){
|
||||
cycles_needed += SAMPLES_PER_AUDIO_TICK;
|
||||
if(cycles_needed > 1){
|
||||
//printf("tick\n");
|
||||
while(ctx.buffer_cnt == AUDIO_BUFFER_SIZE){
|
||||
//if(ctx.buffer_cnt == AUDIO_BUFFER_SIZE){
|
||||
//ctx.buffer_cnt--;
|
||||
//ctx.sq1_read_index++;
|
||||
//ctx.sq1_read_index %= AUDIO_BUFFER_SIZE;
|
||||
delay(10);
|
||||
//delay(1);
|
||||
//printf("overflow\n");
|
||||
//return;
|
||||
//}
|
||||
cycles_needed -= 1;
|
||||
|
||||
bool dacs = ctx.ch1_dac || ctx.ch2_dac || ctx.ch3_dac || ctx.ch4_dac;
|
||||
float left_out = 0;
|
||||
float right_out = 0;
|
||||
if(dacs) {
|
||||
left_out = smooth_left - left_cap;
|
||||
right_out = smooth_right - right_cap;
|
||||
left_cap = smooth_left - left_out * 0.996f;
|
||||
right_cap = smooth_right - right_out * 0.996f;
|
||||
}
|
||||
ctx.sq1_audio_buffer[(ctx.sq1_write_index)] = smooth_left;
|
||||
ctx.sq2_audio_buffer[(ctx.sq1_write_index)] = smooth_right;
|
||||
|
||||
|
||||
left_out /= 4;
|
||||
right_out /= 4;
|
||||
|
||||
if(left_out < -1.0f) {
|
||||
left_out = -1;
|
||||
}
|
||||
if(left_out > 1.0f) {
|
||||
left_out = 1;
|
||||
}
|
||||
if(right_out < -1.0f) {
|
||||
right_out = -1;
|
||||
}
|
||||
if(right_out > 1.0f) {
|
||||
right_out = 1;
|
||||
}
|
||||
|
||||
ctx.sq1_audio_buffer[(ctx.sq1_write_index)] = left_out;
|
||||
ctx.sq2_audio_buffer[(ctx.sq1_write_index)] = right_out;
|
||||
//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++;
|
||||
ctx.sq1_write_index = (ctx.sq1_write_index + 1);
|
||||
//ctx.buffer_cnt++;
|
||||
if(ctx.sq1_write_index == FRAMES_PER_BUFFER) {
|
||||
ctx.sq1_write_index = 0;
|
||||
float *data[2];
|
||||
data[0] = ctx.sq1_audio_buffer;
|
||||
data[1] = ctx.sq2_audio_buffer;
|
||||
int err = Pa_WriteStream(stream, data, FRAMES_PER_BUFFER);
|
||||
if(err != paNoError) {
|
||||
fprintf(stderr, "portaudio stream error\n\tError Number: %d\n\tError Message: %s\n", err, Pa_GetErrorText(err));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool skipped = false;
|
||||
void audio_period_tick() {
|
||||
period_tick++;
|
||||
u32 end = get_ticks();
|
||||
samples_per_sec++;
|
||||
if (end - start >= 1000) {
|
||||
printf("Samples In Buffer: %ld\n", ctx.buffer_cnt);
|
||||
start = end;
|
||||
samples_per_sec = 0;
|
||||
}
|
||||
if(period_tick % 2 == 0){
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,7 @@ void timer_tick() {
|
||||
}
|
||||
}
|
||||
|
||||
lfsr_tick();
|
||||
audio_sample_tick();
|
||||
|
||||
if((prev_div & (1 << 12)) && (!(ctx.div & (1 << 12)))){
|
||||
audio_tick();
|
||||
|
Loading…
Reference in New Issue
Block a user