changeset 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 5257e85364ed
files psg.c psg.h
diffstat 2 files changed, 12 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/psg.c	Tue Apr 19 00:38:44 2016 -0700
+++ b/psg.c	Wed Apr 20 00:18:01 2016 -0700
@@ -9,6 +9,8 @@
 #include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <math.h>
+#define LOWPASS_CUTOFF 3390
 
 void psg_init(psg_context * context, uint32_t sample_rate, uint32_t master_clock, uint32_t clock_div, uint32_t samples_frame)
 {
@@ -18,6 +20,10 @@
 	context->clock_inc = clock_div;
 	context->sample_rate = sample_rate;
 	context->samples_frame = samples_frame;
+	double rc = (1.0 / (double)LOWPASS_CUTOFF) / (2.0 * M_PI);
+	double dt = 1.0 / ((double)master_clock / (double)clock_div);
+	double alpha = dt / (dt + rc);
+	context->lowpass_alpha = (int32_t)(((double)0x10000) * alpha);
 	psg_adjust_master_clock(context, master_clock);
 	for (int i = 0; i < 4; i++) {
 		context->volume[i] = 0xF;
@@ -127,18 +133,16 @@
 		if (context->noise_out) {
 			context->accum += volume_table[context->volume[3]];
 		}
-		context->sample_count++;
+		int32_t tmp = context->accum * context->lowpass_alpha + context->last_sample * (0x10000 - context->lowpass_alpha);
+		context->accum = tmp >> 16;
 
 		context->buffer_fraction += context->buffer_inc;
 		if (context->buffer_fraction >= BUFFER_INC_RES) {
 			context->buffer_fraction -= BUFFER_INC_RES;
-			uint32_t tmp = context->last_sample * (0x10000 - ((context->buffer_fraction << 16) / context->buffer_inc));
-			tmp += context->accum * ((context->buffer_fraction << 16) / context->buffer_inc);
-			printf("Last: %d, Cur: %d, Fraction: %d, Inc: %d, Result: %d, Samples: %d, Float: %f, Fixed: %X\n", 
-				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));
-
+			int32_t tmp = context->last_sample * ((context->buffer_fraction << 16) / context->buffer_inc);
+			tmp += context->accum * (0x10000 - ((context->buffer_fraction << 16) / context->buffer_inc));
 			context->audio_buffer[context->buffer_pos++] = tmp >> 16;
-			context->sample_count = 0;
+			
 			if (context->buffer_pos == context->samples_frame) {
 				if (!headless) {
 					render_wait_psg(context);
--- a/psg.h	Tue Apr 19 00:38:44 2016 -0700
+++ b/psg.h	Wed Apr 20 00:18:01 2016 -0700
@@ -18,12 +18,12 @@
 	uint32_t cycles;
 	uint32_t sample_rate;
 	uint32_t samples_frame;
+	int32_t lowpass_alpha;
 	uint16_t lsfr;
 	uint16_t counter_load[4];
 	uint16_t counters[4];
 	int16_t  accum;
 	int16_t  last_sample;
-	int16_t  sample_count;
 	uint8_t  volume[4];
 	uint8_t  output_state[4];
 	uint8_t  noise_out;