@@ -192,7 +192,7 @@ static void synth_note_into_buffer(synthio_synth_t *synth, int chan, int32_t *ou
192192
193193 uint32_t dds_rate ;
194194 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 ) ;
196196
197197 uint32_t ring_dds_rate = 0 ;
198198 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
213213 int32_t frequency_scaled = synthio_note_step (note , sample_rate , dur , loudness );
214214 if (note -> waveform_buf .buf ) {
215215 waveform = note -> waveform_buf .buf ;
216- waveform_length = note -> waveform_buf .len / 2 ;
216+ waveform_length = note -> waveform_buf .len / sizeof ( int16_t ) ;
217217 }
218218 dds_rate = synthio_frequency_convert_scaled_to_dds ((uint64_t )frequency_scaled * waveform_length , sample_rate );
219219 if (note -> ring_frequency_scaled != 0 && note -> ring_waveform_buf .buf ) {
220220 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 ) ;
222222 ring_dds_rate = synthio_frequency_convert_scaled_to_dds ((uint64_t )note -> ring_frequency_scaled * ring_waveform_length , sample_rate );
223223 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 ) ) {
225225 ring_dds_rate = 0 ; // can't ring at that frequency
226226 }
227227 }
@@ -309,6 +309,37 @@ static void synth_note_into_buffer(synthio_synth_t *synth, int chan, int32_t *ou
309309 }
310310}
311311
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+
312343void synthio_synth_synthesize (synthio_synth_t * synth , uint8_t * * bufptr , uint32_t * buffer_length , uint8_t channel ) {
313344
314345 if (channel == synth -> other_channel ) {
@@ -326,12 +357,31 @@ void synthio_synth_synthesize(synthio_synth_t *synth, uint8_t **bufptr, uint32_t
326357
327358 int32_t out_buffer32 [dur * synth -> channel_count ];
328359
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+
330377 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+ }
331382 synth_note_into_buffer (synth , chan , out_buffer32 , dur );
332383 }
333384
334-
335385 int16_t * out_buffer16 = (int16_t * )(void * )synth -> buffers [synth -> buffer_index ];
336386
337387 // mix down audio
@@ -387,7 +437,7 @@ void synthio_synth_init(synthio_synth_t *synth, uint32_t sample_rate, int channe
387437 synth -> buffers [0 ] = m_malloc (synth -> buffer_length , false);
388438 synth -> buffers [1 ] = m_malloc (synth -> buffer_length , false);
389439 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 );
391441 synth -> filter_buffer = m_malloc (synth -> filter_buffer_length , false);
392442 }
393443 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
419469 if (bufinfo -> typecode != 'h' ) {
420470 mp_raise_ValueError_varg (translate ("%q must be array of type 'h'" ), what );
421471 }
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 );
423473 }
424474}
425475
0 commit comments