@@ -49,7 +49,7 @@ static struct chan {
49
49
50
50
// square
51
51
int duty ;
52
- float fval ;
52
+ int duty_counter ;
53
53
54
54
// noise
55
55
uint16_t lfsr_reg ;
@@ -58,7 +58,7 @@ static struct chan {
58
58
59
59
// wave
60
60
int sample_cursor ;
61
- float sample ;
61
+ uint8_t sample ;
62
62
} chans [4 ];
63
63
64
64
#define FREQ 44100.0f
@@ -69,7 +69,7 @@ static size_t nsamples;
69
69
static float * samples ;
70
70
71
71
static SDL_AudioDeviceID audio ;
72
- static const float duty [] = { 0.125 , 0.25 , 0.5 , 0.75 };
72
+ static const int duty_lookup [] = { 1 , 2 , 4 , 6 };
73
73
static float logbase ;
74
74
static float vol_l , vol_r ;
75
75
static const char * notes [] = {
@@ -119,7 +119,6 @@ void update_env(struct chan* c){
119
119
}
120
120
121
121
void update_len (struct chan * c ){
122
-
123
122
if (c -> len .enabled ){
124
123
c -> len .counter += c -> len .inc ;
125
124
if (c -> len .counter > 1.0f ){
@@ -129,16 +128,18 @@ void update_len(struct chan* c){
129
128
}
130
129
}
131
130
132
- int update_freq (struct chan * c ){
133
- c -> freq_counter += c -> freq_inc ;
131
+ bool update_freq (struct chan * c , float * pos ){
132
+ float inc = c -> freq_inc - * pos ;
133
+ c -> freq_counter += inc ;
134
134
135
- int result = 0 ;
136
- while (c -> freq_counter > 1.0f ){
137
- c -> freq_counter -= 1.0f ;
138
- result ++ ;
135
+ if (c -> freq_counter > 1.0f ){
136
+ * pos = c -> freq_inc - (c -> freq_counter - 1.0f );
137
+ c -> freq_counter = 0.0f ;
138
+ return true;
139
+ } else {
140
+ * pos = c -> freq_inc ;
141
+ return false;
139
142
}
140
-
141
- return result ;
142
143
}
143
144
144
145
void update_sweep (struct chan * c ){
@@ -152,23 +153,21 @@ void update_sweep(struct chan* c){
152
153
c -> freq += inc ;
153
154
c -> sweep .freq = c -> freq ;
154
155
155
- set_note_freq (c , 4194304 / (float )((2048 - c -> freq ) << 5 ));
156
+ set_note_freq (c , 4194304.0f / (float )((2048 - c -> freq ) << 5 ));
157
+ c -> freq_inc *= 8.0f ;
156
158
} else {
157
159
c -> enabled = 0 ;
158
160
}
159
161
c -> sweep .counter -= 1.0f ;
160
162
}
161
163
}
162
164
163
- float lerp (float a , float b , float t ){
164
- return a + (b - a ) * t ;
165
- }
166
-
167
165
void update_square (bool ch2 ){
168
166
struct chan * c = chans + ch2 ;
169
167
if (!c -> powered ) return ;
170
168
171
169
set_note_freq (c , 4194304.0f / (float )((2048 - c -> freq ) << 5 ));
170
+ c -> freq_inc *= 8.0f ;
172
171
173
172
for (int i = 0 ; i < nsamples ; i += 2 ){
174
173
update_len (c );
@@ -177,16 +176,21 @@ void update_square(bool ch2){
177
176
update_env (c );
178
177
if (!ch2 ) update_sweep (c );
179
178
180
- float d ;
181
- if (update_freq (c )){
182
- c -> fval = (2 * c -> freq_counter - c -> freq_inc ) / c -> freq_inc ;
183
- } else if ((d = c -> freq_counter - duty [c -> duty ]) > 0.0f ){
184
- c -> fval = MAX (-1.0f , (c -> freq_inc - 2 * d ) / c -> freq_inc );
185
- } else {
186
- c -> fval = 1.0f ;
187
- }
179
+ float pos = 0.0f ;
180
+ float prev_pos = 0.0f ;
181
+ float sample = 0.0f ;
188
182
189
- float sample = hipass (c , c -> fval * (c -> volume / 15.0f ));
183
+ while (update_freq (c , & pos )){
184
+ c -> duty_counter = (c -> duty_counter + 1 ) & 7 ;
185
+ sample += ((pos - prev_pos ) / c -> freq_inc ) * (float )c -> val ;
186
+
187
+ if (!c -> duty_counter || c -> duty_counter == c -> duty ){
188
+ c -> val = ~(c -> val - 1 );
189
+ }
190
+ prev_pos = pos ;
191
+ }
192
+ sample += ((pos - prev_pos ) / c -> freq_inc ) * (float )c -> val ;
193
+ sample = hipass (c , sample * (c -> volume / 15.0f ));
190
194
191
195
if (!c -> user_mute ){
192
196
samples [i + 0 ] += sample * 0.25f * c -> on_left * vol_l ;
@@ -200,34 +204,41 @@ void update_wave(void){
200
204
struct chan * c = chans + 2 ;
201
205
if (!c -> powered ) return ;
202
206
203
- set_note_freq (c , 4194304 / (float )((2048 - c -> freq ) << 5 ));
204
- c -> freq_inc *= 16.0f ;
207
+ float freq = 4194304.0f / (float )((2048 - c -> freq ) << 5 );
208
+ set_note_freq (c , freq );
209
+
210
+ if (freq >= 131079 ) c -> enabled = false;
211
+ else c -> freq_inc *= 16.0f ;
205
212
206
213
for (int i = 0 ; i < nsamples ; i += 2 ){
207
214
update_len (c );
208
215
209
216
if (c -> enabled ){
210
- float t = 1.0f ;
217
+ float pos = 0.0f ;
218
+ float prev_pos = 0.0f ;
219
+ float sample = 0.0f ;
211
220
212
- if (update_freq (c )){
221
+ while (update_freq (c , & pos )){
213
222
c -> sample_cursor = c -> val ;
214
223
c -> val = (c -> val + 1 ) & 31 ;
215
- t = c -> freq_counter / c -> freq_inc ;
216
- }
217
224
218
- uint8_t s = mem [0xFF30 + c -> sample_cursor / 2 ];
219
- if (c -> sample_cursor & 1 ){
220
- s &= 0xF ;
221
- } else {
222
- s >>= 4 ;
225
+ c -> sample = mem [0xFF30 + c -> sample_cursor / 2 ];
226
+ if (c -> sample_cursor & 1 ){
227
+ c -> sample &= 0xF ;
228
+ } else {
229
+ c -> sample >>= 4 ;
230
+ }
231
+
232
+ c -> sample = (c -> volume ) ? (c -> sample >> (c -> volume - 1 )) : 0 ;
233
+ sample += ((pos - prev_pos ) / c -> freq_inc ) * c -> sample ;
234
+ prev_pos = pos ;
223
235
}
236
+ sample += ((pos - prev_pos ) / c -> freq_inc ) * c -> sample ;
224
237
225
238
if (c -> volume > 0 ){
226
- s >>= (c -> volume - 1 );
227
239
float diff = (float []){ 7.5f , 3.75f , 1.5f }[c -> volume - 1 ];
228
- c -> sample = lerp ( c -> sample , (float ) s , t );
240
+ sample = hipass ( c , (sample - diff ) / 7.5f );
229
241
230
- float sample = hipass (c , (c -> sample - diff ) / 7.5f );
231
242
if (!c -> user_mute ){
232
243
samples [i + 0 ] += sample * 0.25f * c -> on_left * vol_l ;
233
244
samples [i + 1 ] += sample * 0.25f * c -> on_right * vol_r ;
@@ -250,24 +261,24 @@ void update_noise(void){
250
261
if (c -> enabled ){
251
262
update_env (c );
252
263
253
- float sample = c -> val ;
254
- int count = update_freq (c );
255
- for (int j = 0 ; j < count ; ++ j ){
264
+ float pos = 0.0f ;
265
+ float prev_pos = 0.0f ;
266
+ float sample = 0.0f ;
267
+
268
+ while (update_freq (c , & pos )){
256
269
c -> lfsr_reg = (c -> lfsr_reg << 1 ) | (c -> val == 1 );
257
270
258
271
if (c -> lfsr_wide ){
259
272
c -> val = !(((c -> lfsr_reg >> 14 ) & 1 ) ^ ((c -> lfsr_reg >> 13 ) & 1 )) ? 1 : -1 ;
260
273
} else {
261
274
c -> val = !(((c -> lfsr_reg >> 6 ) & 1 ) ^ ((c -> lfsr_reg >> 5 ) & 1 )) ? 1 : -1 ;
262
275
}
263
- sample += c -> val ;
276
+ sample += ((pos - prev_pos ) / c -> freq_inc ) * c -> val ;
277
+ prev_pos = pos ;
264
278
}
265
-
266
- if (count ){
267
- sample /= (float )count ;
268
- }
269
-
279
+ sample += ((pos - prev_pos ) / c -> freq_inc ) * c -> val ;
270
280
sample = hipass (c , sample * (c -> volume / 15.0f ));
281
+
271
282
if (!c -> user_mute ){
272
283
samples [i + 0 ] += sample * 0.25f * c -> on_left * vol_l ;
273
284
samples [i + 1 ] += sample * 0.25f * c -> on_right * vol_r ;
@@ -330,6 +341,7 @@ void audio_reset(void){
330
341
memset (chans , 0 , sizeof (chans ));
331
342
memset (samples , 0 , nsamples * sizeof (float ));
332
343
SDL_ClearQueuedAudio (audio );
344
+ chans [0 ].val = chans [1 ].val = 1 ;
333
345
}
334
346
335
347
void audio_init (void ){
@@ -420,18 +432,14 @@ void chan_trigger(int i){
420
432
421
433
if (i == 2 ){ // wave
422
434
len_max = 256 ;
435
+ c -> val = 0 ;
423
436
} else if (i == 3 ){ // noise
424
437
c -> lfsr_reg = 0xFFFF ;
438
+ c -> val = -1 ;
425
439
}
426
440
427
441
c -> len .inc = (256.0f / (float )(len_max - c -> len .load )) / FREQ ;
428
442
c -> len .counter = 0.0f ;
429
-
430
- if (i < 2 ){
431
- c -> val = 1 ;
432
- } else {
433
- c -> val = 0 ;
434
- }
435
443
}
436
444
437
445
void audio_write (uint16_t addr , uint8_t val ){
@@ -479,7 +487,7 @@ void audio_write(uint16_t addr, uint8_t val){
479
487
case 0xFF16 :
480
488
case 0xFF20 :
481
489
chans [i ].len .load = val & 0x3f ;
482
- chans [i ].duty = val >> 6 ;
490
+ chans [i ].duty = duty_lookup [ val >> 6 ] ;
483
491
break ;
484
492
485
493
case 0xFF1B :
0 commit comments