@@ -192,7 +192,7 @@ static void synth_note_into_buffer(synthio_synth_t *synth, int chan, int32_t *ou
192
192
193
193
uint32_t dds_rate ;
194
194
const int16_t * waveform = synth -> waveform_bufinfo .buf ;
195
- uint32_t waveform_length = synth -> waveform_bufinfo .len / 2 ;
195
+ uint32_t waveform_length = synth -> waveform_bufinfo .len / sizeof ( int16_t ) ;
196
196
197
197
uint32_t ring_dds_rate = 0 ;
198
198
const int16_t * ring_waveform = NULL ;
@@ -213,15 +213,15 @@ static void synth_note_into_buffer(synthio_synth_t *synth, int chan, int32_t *ou
213
213
int32_t frequency_scaled = synthio_note_step (note , sample_rate , dur , loudness );
214
214
if (note -> waveform_buf .buf ) {
215
215
waveform = note -> waveform_buf .buf ;
216
- waveform_length = note -> waveform_buf .len / 2 ;
216
+ waveform_length = note -> waveform_buf .len / sizeof ( int16_t ) ;
217
217
}
218
218
dds_rate = synthio_frequency_convert_scaled_to_dds ((uint64_t )frequency_scaled * waveform_length , sample_rate );
219
219
if (note -> ring_frequency_scaled != 0 && note -> ring_waveform_buf .buf ) {
220
220
ring_waveform = note -> ring_waveform_buf .buf ;
221
- ring_waveform_length = note -> ring_waveform_buf .len / 2 ;
221
+ ring_waveform_length = note -> ring_waveform_buf .len / sizeof ( int16_t ) ;
222
222
ring_dds_rate = synthio_frequency_convert_scaled_to_dds ((uint64_t )note -> ring_frequency_scaled * ring_waveform_length , sample_rate );
223
223
uint32_t lim = ring_waveform_length << SYNTHIO_FREQUENCY_SHIFT ;
224
- if (ring_dds_rate > lim / 2 ) {
224
+ if (ring_dds_rate > lim / sizeof ( int16_t ) ) {
225
225
ring_dds_rate = 0 ; // can't ring at that frequency
226
226
}
227
227
}
@@ -309,6 +309,37 @@ static void synth_note_into_buffer(synthio_synth_t *synth, int chan, int32_t *ou
309
309
}
310
310
}
311
311
312
+ STATIC void run_fir (synthio_synth_t * synth , int32_t * out_buffer32 , uint16_t dur ) {
313
+ int16_t * coeff = (int16_t * )synth -> filter_bufinfo .buf ;
314
+ size_t fir_len = synth -> filter_bufinfo .len / sizeof (int16_t );
315
+ int32_t * in_buf = synth -> filter_buffer ;
316
+
317
+ // FIR and copy values to output buffer
318
+ for (int16_t i = 0 ; i < dur ; i ++ ) {
319
+ int32_t acc = 0 ;
320
+ for (size_t j = 0 ; j < fir_len ; j ++ ) {
321
+ // shift 5 here is good for up to 32 filtered voices, else might wrap
322
+ acc = acc + (in_buf [j ] * (coeff [j ] >> 5 ));
323
+ }
324
+ * out_buffer32 ++ = acc >> 10 ;
325
+ in_buf ++ ;
326
+ }
327
+
328
+ // Move values down so that they get filtered next time
329
+ memmove (synth -> filter_buffer , & synth -> filter_buffer [dur ], fir_len * sizeof (int32_t ));
330
+ }
331
+
332
+ STATIC bool synthio_synth_get_note_filtered (mp_obj_t note_obj ) {
333
+ if (note_obj == mp_const_none ) {
334
+ return false;
335
+ }
336
+ if (!mp_obj_is_small_int (note_obj )) {
337
+ synthio_note_obj_t * note = MP_OBJ_TO_PTR (note_obj );
338
+ return note -> filter ;
339
+ }
340
+ return true;
341
+ }
342
+
312
343
void synthio_synth_synthesize (synthio_synth_t * synth , uint8_t * * bufptr , uint32_t * buffer_length , uint8_t channel ) {
313
344
314
345
if (channel == synth -> other_channel ) {
@@ -326,12 +357,31 @@ void synthio_synth_synthesize(synthio_synth_t *synth, uint8_t **bufptr, uint32_t
326
357
327
358
int32_t out_buffer32 [dur * synth -> channel_count ];
328
359
329
- memset (out_buffer32 , 0 , sizeof (out_buffer32 ));
360
+ if (synth -> filter_buffer ) {
361
+ int32_t * filter_start = & synth -> filter_buffer [synth -> filter_bufinfo .len * synth -> channel_count / sizeof (int16_t )];
362
+ memset (filter_start , 0 , dur * sizeof (int32_t ));
363
+
364
+ for (int chan = 0 ; chan < CIRCUITPY_SYNTHIO_MAX_CHANNELS ; chan ++ ) {
365
+ mp_obj_t note_obj = synth -> span .note_obj [chan ];
366
+ if (!synthio_synth_get_note_filtered (note_obj )) {
367
+ continue ;
368
+ }
369
+ synth_note_into_buffer (synth , chan , filter_start , dur );
370
+ }
371
+
372
+ run_fir (synth , out_buffer32 , dur );
373
+ } else {
374
+ memset (out_buffer32 , 0 , sizeof (out_buffer32 ));
375
+ }
376
+
330
377
for (int chan = 0 ; chan < CIRCUITPY_SYNTHIO_MAX_CHANNELS ; chan ++ ) {
378
+ mp_obj_t note_obj = synth -> span .note_obj [chan ];
379
+ if (synth -> filter_buffer && synthio_synth_get_note_filtered (note_obj )) {
380
+ continue ;
381
+ }
331
382
synth_note_into_buffer (synth , chan , out_buffer32 , dur );
332
383
}
333
384
334
-
335
385
int16_t * out_buffer16 = (int16_t * )(void * )synth -> buffers [synth -> buffer_index ];
336
386
337
387
// mix down audio
@@ -387,7 +437,7 @@ void synthio_synth_init(synthio_synth_t *synth, uint32_t sample_rate, int channe
387
437
synth -> buffers [0 ] = m_malloc (synth -> buffer_length , false);
388
438
synth -> buffers [1 ] = m_malloc (synth -> buffer_length , false);
389
439
if (synth -> filter_bufinfo .len ) {
390
- synth -> filter_buffer_length = (synth -> filter_bufinfo .len + SYNTHIO_MAX_DUR ) * channel_count * sizeof (int32_t );
440
+ synth -> filter_buffer_length = (synth -> filter_bufinfo .len / 2 + SYNTHIO_MAX_DUR ) * channel_count * sizeof (int32_t );
391
441
synth -> filter_buffer = m_malloc (synth -> filter_buffer_length , false);
392
442
}
393
443
synth -> channel_count = channel_count ;
@@ -419,7 +469,7 @@ STATIC void parse_common(mp_buffer_info_t *bufinfo, mp_obj_t o, int16_t what, mp
419
469
if (bufinfo -> typecode != 'h' ) {
420
470
mp_raise_ValueError_varg (translate ("%q must be array of type 'h'" ), what );
421
471
}
422
- mp_arg_validate_length_range (bufinfo -> len / 2 , 2 , max_len , what );
472
+ mp_arg_validate_length_range (bufinfo -> len / sizeof ( int16_t ) , 2 , max_len , what );
423
473
}
424
474
}
425
475
0 commit comments