comparison psg.c @ 1555:6ce36c3f250b

More audio refactoring in preparation for allowing proper sync to video with dynamic audio rate control
author Michael Pavone <pavone@retrodev.com>
date Fri, 30 Mar 2018 00:37:08 -0700
parents ce1f93be0104
children 4c322abd9fa5
comparison
equal deleted inserted replaced
1554:87350caf6dab 1555:6ce36c3f250b
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> 12 #include <math.h>
13 void psg_init(psg_context * context, uint32_t sample_rate, uint32_t master_clock, uint32_t clock_div, uint32_t samples_frame, uint32_t lowpass_cutoff) 13 void psg_init(psg_context * context, uint32_t master_clock, uint32_t clock_div)
14 { 14 {
15 memset(context, 0, sizeof(*context)); 15 memset(context, 0, sizeof(*context));
16 context->audio = render_audio_source(1); 16 context->audio = render_audio_source(master_clock, clock_div, 1);
17 context->audio_buffer = render_audio_source_buffer(context->audio);
18 context->clock_inc = clock_div; 17 context->clock_inc = clock_div;
19 context->sample_rate = sample_rate;
20 context->samples_frame = samples_frame;
21 double rc = (1.0 / (double)lowpass_cutoff) / (2.0 * M_PI);
22 double dt = 1.0 / ((double)master_clock / (double)clock_div);
23 double alpha = dt / (dt + rc);
24 context->lowpass_alpha = (int32_t)(((double)0x10000) * alpha);
25 psg_adjust_master_clock(context, master_clock);
26 for (int i = 0; i < 4; i++) { 18 for (int i = 0; i < 4; i++) {
27 context->volume[i] = 0xF; 19 context->volume[i] = 0xF;
28 } 20 }
29 } 21 }
30 22
32 { 24 {
33 render_free_source(context->audio); 25 render_free_source(context->audio);
34 free(context); 26 free(context);
35 } 27 }
36 28
37 #define BUFFER_INC_RES 0x40000000UL
38
39 void psg_adjust_master_clock(psg_context * context, uint32_t master_clock) 29 void psg_adjust_master_clock(psg_context * context, uint32_t master_clock)
40 { 30 {
41 uint64_t old_inc = context->buffer_inc; 31 render_audio_adjust_clock(context->audio, master_clock, context->clock_inc);
42 context->buffer_inc = ((BUFFER_INC_RES * (uint64_t)context->sample_rate) / (uint64_t)master_clock) * (uint64_t)context->clock_inc;
43 } 32 }
44 33
45 void psg_write(psg_context * context, uint8_t value) 34 void psg_write(psg_context * context, uint8_t value)
46 { 35 {
47 if (value & 0x80) { 36 if (value & 0x80) {
115 } 104 }
116 } 105 }
117 } 106 }
118 } 107 }
119 108
120 context->last_sample = context->accum; 109 int16_t accum = 0;
121 context->accum = 0;
122 110
123 for (int i = 0; i < 3; i++) { 111 for (int i = 0; i < 3; i++) {
124 if (context->output_state[i]) { 112 if (context->output_state[i]) {
125 context->accum += volume_table[context->volume[i]]; 113 accum += volume_table[context->volume[i]];
126 } 114 }
127 } 115 }
128 if (context->noise_out) { 116 if (context->noise_out) {
129 context->accum += volume_table[context->volume[3]]; 117 accum += volume_table[context->volume[3]];
130 } 118 }
131 int32_t tmp = context->accum * context->lowpass_alpha + context->last_sample * (0x10000 - context->lowpass_alpha); 119
132 context->accum = tmp >> 16; 120 render_put_mono_sample(context->audio, accum);
133 121
134 context->buffer_fraction += context->buffer_inc;
135 while (context->buffer_fraction >= BUFFER_INC_RES) {
136 context->buffer_fraction -= BUFFER_INC_RES;
137 int32_t tmp = context->last_sample * ((context->buffer_fraction << 16) / context->buffer_inc);
138 tmp += context->accum * (0x10000 - ((context->buffer_fraction << 16) / context->buffer_inc));
139 context->audio_buffer[context->buffer_pos++] = tmp >> 16;
140
141 if (context->buffer_pos == context->samples_frame) {
142 if (!headless) {
143 context->audio_buffer = render_audio_ready(context->audio);
144 context->buffer_pos = 0;
145 }
146 }
147 }
148 context->cycles += context->clock_inc; 122 context->cycles += context->clock_inc;
149 } 123 }
150 } 124 }
151 125
152 void psg_serialize(psg_context *context, serialize_buffer *buf) 126 void psg_serialize(psg_context *context, serialize_buffer *buf)