comparison psg.c @ 964:e6dc30231b83

Fix PSG linear resampling and implement a low pass filter
author Michael Pavone <pavone@retrodev.com>
date Wed, 20 Apr 2016 00:18:01 -0700
parents bd549b25c362
children 8d032a368dd5
comparison
equal deleted inserted replaced
963:bd549b25c362 964:e6dc30231b83
7 #include "render.h" 7 #include "render.h"
8 #include "blastem.h" 8 #include "blastem.h"
9 #include <string.h> 9 #include <string.h>
10 #include <stdlib.h> 10 #include <stdlib.h>
11 #include <stdio.h> 11 #include <stdio.h>
12 #include <math.h>
13 #define LOWPASS_CUTOFF 3390
12 14
13 void psg_init(psg_context * context, uint32_t sample_rate, uint32_t master_clock, uint32_t clock_div, uint32_t samples_frame) 15 void psg_init(psg_context * context, uint32_t sample_rate, uint32_t master_clock, uint32_t clock_div, uint32_t samples_frame)
14 { 16 {
15 memset(context, 0, sizeof(*context)); 17 memset(context, 0, sizeof(*context));
16 context->audio_buffer = malloc(sizeof(*context->audio_buffer) * samples_frame); 18 context->audio_buffer = malloc(sizeof(*context->audio_buffer) * samples_frame);
17 context->back_buffer = malloc(sizeof(*context->audio_buffer) * samples_frame); 19 context->back_buffer = malloc(sizeof(*context->audio_buffer) * samples_frame);
18 context->clock_inc = clock_div; 20 context->clock_inc = clock_div;
19 context->sample_rate = sample_rate; 21 context->sample_rate = sample_rate;
20 context->samples_frame = samples_frame; 22 context->samples_frame = samples_frame;
23 double rc = (1.0 / (double)LOWPASS_CUTOFF) / (2.0 * M_PI);
24 double dt = 1.0 / ((double)master_clock / (double)clock_div);
25 double alpha = dt / (dt + rc);
26 context->lowpass_alpha = (int32_t)(((double)0x10000) * alpha);
21 psg_adjust_master_clock(context, master_clock); 27 psg_adjust_master_clock(context, master_clock);
22 for (int i = 0; i < 4; i++) { 28 for (int i = 0; i < 4; i++) {
23 context->volume[i] = 0xF; 29 context->volume[i] = 0xF;
24 } 30 }
25 } 31 }
125 } 131 }
126 } 132 }
127 if (context->noise_out) { 133 if (context->noise_out) {
128 context->accum += volume_table[context->volume[3]]; 134 context->accum += volume_table[context->volume[3]];
129 } 135 }
130 context->sample_count++; 136 int32_t tmp = context->accum * context->lowpass_alpha + context->last_sample * (0x10000 - context->lowpass_alpha);
137 context->accum = tmp >> 16;
131 138
132 context->buffer_fraction += context->buffer_inc; 139 context->buffer_fraction += context->buffer_inc;
133 if (context->buffer_fraction >= BUFFER_INC_RES) { 140 if (context->buffer_fraction >= BUFFER_INC_RES) {
134 context->buffer_fraction -= BUFFER_INC_RES; 141 context->buffer_fraction -= BUFFER_INC_RES;
135 uint32_t tmp = context->last_sample * (0x10000 - ((context->buffer_fraction << 16) / context->buffer_inc)); 142 int32_t tmp = context->last_sample * ((context->buffer_fraction << 16) / context->buffer_inc);
136 tmp += context->accum * ((context->buffer_fraction << 16) / context->buffer_inc); 143 tmp += context->accum * (0x10000 - ((context->buffer_fraction << 16) / context->buffer_inc));
137 printf("Last: %d, Cur: %d, Fraction: %d, Inc: %d, Result: %d, Samples: %d, Float: %f, Fixed: %X\n",
138 context->last_sample, context->accum, (int)context->buffer_fraction, (int)context->buffer_inc, tmp >> 16, context->sample_count, (float)context->buffer_fraction/(float)context->buffer_inc, (int)((context->buffer_fraction << 16) / context->buffer_inc));
139
140 context->audio_buffer[context->buffer_pos++] = tmp >> 16; 144 context->audio_buffer[context->buffer_pos++] = tmp >> 16;
141 context->sample_count = 0; 145
142 if (context->buffer_pos == context->samples_frame) { 146 if (context->buffer_pos == context->samples_frame) {
143 if (!headless) { 147 if (!headless) {
144 render_wait_psg(context); 148 render_wait_psg(context);
145 } 149 }
146 } 150 }