comparison psg.c @ 1692:5dacaef602a7 segacd

Merge from default
author Michael Pavone <pavone@retrodev.com>
date Sat, 05 Jan 2019 00:58:08 -0800
parents 6ce36c3f250b
children 4c322abd9fa5
comparison
equal deleted inserted replaced
1504:95b3a1a8b26c 1692:5dacaef602a7
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_buffer = malloc(sizeof(*context->audio_buffer) * samples_frame); 16 context->audio = render_audio_source(master_clock, clock_div, 1);
17 context->back_buffer = malloc(sizeof(*context->audio_buffer) * samples_frame);
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
31 void psg_free(psg_context *context) 23 void psg_free(psg_context *context)
32 { 24 {
33 free(context->audio_buffer); 25 render_free_source(context->audio);
34 //TODO: Figure out how to make this 100% safe
35 //audio thread could still be using this
36 free(context->back_buffer);
37 free(context); 26 free(context);
38 } 27 }
39 28
40 #define BUFFER_INC_RES 0x40000000UL
41
42 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)
43 { 30 {
44 uint64_t old_inc = context->buffer_inc; 31 render_audio_adjust_clock(context->audio, master_clock, context->clock_inc);
45 context->buffer_inc = ((BUFFER_INC_RES * (uint64_t)context->sample_rate) / (uint64_t)master_clock) * (uint64_t)context->clock_inc;
46 } 32 }
47 33
48 void psg_write(psg_context * context, uint8_t value) 34 void psg_write(psg_context * context, uint8_t value)
49 { 35 {
50 if (value & 0x80) { 36 if (value & 0x80) {
118 } 104 }
119 } 105 }
120 } 106 }
121 } 107 }
122 108
123 context->last_sample = context->accum; 109 int16_t accum = 0;
124 context->accum = 0;
125 110
126 for (int i = 0; i < 3; i++) { 111 for (int i = 0; i < 3; i++) {
127 if (context->output_state[i]) { 112 if (context->output_state[i]) {
128 context->accum += volume_table[context->volume[i]]; 113 accum += volume_table[context->volume[i]];
129 } 114 }
130 } 115 }
131 if (context->noise_out) { 116 if (context->noise_out) {
132 context->accum += volume_table[context->volume[3]]; 117 accum += volume_table[context->volume[3]];
133 } 118 }
134 int32_t tmp = context->accum * context->lowpass_alpha + context->last_sample * (0x10000 - context->lowpass_alpha); 119
135 context->accum = tmp >> 16; 120 render_put_mono_sample(context->audio, accum);
136 121
137 context->buffer_fraction += context->buffer_inc;
138 while (context->buffer_fraction >= BUFFER_INC_RES) {
139 context->buffer_fraction -= BUFFER_INC_RES;
140 int32_t tmp = context->last_sample * ((context->buffer_fraction << 16) / context->buffer_inc);
141 tmp += context->accum * (0x10000 - ((context->buffer_fraction << 16) / context->buffer_inc));
142 context->audio_buffer[context->buffer_pos++] = tmp >> 16;
143
144 if (context->buffer_pos == context->samples_frame) {
145 if (!headless) {
146 render_wait_psg(context);
147 }
148 }
149 }
150 context->cycles += context->clock_inc; 122 context->cycles += context->clock_inc;
151 } 123 }
152 } 124 }
153 125
154 void psg_serialize(psg_context *context, serialize_buffer *buf) 126 void psg_serialize(psg_context *context, serialize_buffer *buf)