@@ -171,160 +171,167 @@ int16_t mix_down_sample(int32_t sample) {
171171 return sample ;
172172}
173173
174- void synthio_synth_synthesize (synthio_synth_t * synth , uint8_t * * bufptr , uint32_t * buffer_length , uint8_t channel ) {
174+ static void synth_note_into_buffer (synthio_synth_t * synth , int chan , int32_t * out_buffer32 , int16_t dur ) {
175+ mp_obj_t note_obj = synth -> span .note_obj [chan ];
175176
176- if (channel == synth -> other_channel ) {
177- * buffer_length = synth -> last_buffer_length ;
178- * bufptr = (uint8_t * )(synth -> buffers [synth -> other_buffer_index ] + channel );
177+ if (note_obj == SYNTHIO_SILENCE ) {
178+ synth -> accum [chan ] = 0 ;
179179 return ;
180180 }
181181
182- synth -> buffer_index = !synth -> buffer_index ;
183- synth -> other_channel = 1 - channel ;
184- synth -> other_buffer_index = synth -> buffer_index ;
185-
186- uint16_t dur = MIN (SYNTHIO_MAX_DUR , synth -> span .dur );
187- synth -> span .dur -= dur ;
182+ if (synth -> envelope_state [chan ].level == 0 ) {
183+ // note is truly finished, but we only just noticed
184+ synth -> span .note_obj [chan ] = SYNTHIO_SILENCE ;
185+ return ;
186+ }
188187
189188 int32_t sample_rate = synth -> sample_rate ;
190- int32_t out_buffer32 [dur * synth -> channel_count ];
191-
192- memset (out_buffer32 , 0 , sizeof (out_buffer32 ));
193- for (int chan = 0 ; chan < CIRCUITPY_SYNTHIO_MAX_CHANNELS ; chan ++ ) {
194- mp_obj_t note_obj = synth -> span .note_obj [chan ];
195- if (note_obj == SYNTHIO_SILENCE ) {
196- synth -> accum [chan ] = 0 ;
197- continue ;
198- }
199189
200- if (synth -> envelope_state [chan ].level == 0 ) {
201- // note is truly finished, but we only just noticed
202- synth -> span .note_obj [chan ] = SYNTHIO_SILENCE ;
203- continue ;
190+ // adjust loudness by envelope
191+ uint16_t loudness [2 ] = {synth -> envelope_state [chan ].level ,synth -> envelope_state [chan ].level };
192+
193+ uint32_t dds_rate ;
194+ const int16_t * waveform = synth -> waveform_bufinfo .buf ;
195+ uint32_t waveform_length = synth -> waveform_bufinfo .len / 2 ;
196+
197+ uint32_t ring_dds_rate = 0 ;
198+ const int16_t * ring_waveform = NULL ;
199+ uint32_t ring_waveform_length = 0 ;
200+
201+ if (mp_obj_is_small_int (note_obj )) {
202+ uint8_t note = mp_obj_get_int (note_obj );
203+ uint8_t octave = note / 12 ;
204+ uint16_t base_freq = notes [note % 12 ];
205+ // rate = base_freq * waveform_length
206+ // den = sample_rate * 2 ^ (10 - octave)
207+ // den = sample_rate * 2 ^ 10 / 2^octave
208+ // dds_rate = 2^SHIFT * rate / den
209+ // dds_rate = 2^(SHIFT-10+octave) * base_freq * waveform_length / sample_rate
210+ dds_rate = (sample_rate / 2 + ((uint64_t )(base_freq * waveform_length ) << (SYNTHIO_FREQUENCY_SHIFT - 10 + octave ))) / sample_rate ;
211+ } else {
212+ synthio_note_obj_t * note = MP_OBJ_TO_PTR (note_obj );
213+ int32_t frequency_scaled = synthio_note_step (note , sample_rate , dur , loudness );
214+ if (note -> waveform_buf .buf ) {
215+ waveform = note -> waveform_buf .buf ;
216+ waveform_length = note -> waveform_buf .len / 2 ;
204217 }
205-
206- // adjust loudness by envelope
207- uint16_t loudness [2 ] = {synth -> envelope_state [chan ].level ,synth -> envelope_state [chan ].level };
208-
209- uint32_t dds_rate ;
210- const int16_t * waveform = synth -> waveform ;
211- uint32_t waveform_length = synth -> waveform_length ;
212-
213- uint32_t ring_dds_rate = 0 ;
214- const int16_t * ring_waveform = NULL ;
215- uint32_t ring_waveform_length = 0 ;
216-
217- if (mp_obj_is_small_int (note_obj )) {
218- uint8_t note = mp_obj_get_int (note_obj );
219- uint8_t octave = note / 12 ;
220- uint16_t base_freq = notes [note % 12 ];
221- // rate = base_freq * waveform_length
222- // den = sample_rate * 2 ^ (10 - octave)
223- // den = sample_rate * 2 ^ 10 / 2^octave
224- // dds_rate = 2^SHIFT * rate / den
225- // dds_rate = 2^(SHIFT-10+octave) * base_freq * waveform_length / sample_rate
226- dds_rate = (sample_rate / 2 + ((uint64_t )(base_freq * waveform_length ) << (SYNTHIO_FREQUENCY_SHIFT - 10 + octave ))) / sample_rate ;
227- } else {
228- synthio_note_obj_t * note = MP_OBJ_TO_PTR (note_obj );
229- int32_t frequency_scaled = synthio_note_step (note , sample_rate , dur , loudness );
230- if (note -> waveform_buf .buf ) {
231- waveform = note -> waveform_buf .buf ;
232- waveform_length = note -> waveform_buf .len / 2 ;
233- }
234- dds_rate = synthio_frequency_convert_scaled_to_dds ((uint64_t )frequency_scaled * waveform_length , sample_rate );
235- if (note -> ring_frequency_scaled != 0 && note -> ring_waveform_buf .buf ) {
236- ring_waveform = note -> ring_waveform_buf .buf ;
237- ring_waveform_length = note -> ring_waveform_buf .len / 2 ;
238- ring_dds_rate = synthio_frequency_convert_scaled_to_dds ((uint64_t )note -> ring_frequency_scaled * ring_waveform_length , sample_rate );
239- uint32_t lim = ring_waveform_length << SYNTHIO_FREQUENCY_SHIFT ;
240- if (ring_dds_rate > lim / 2 ) {
241- ring_dds_rate = 0 ; // can't ring at that frequency
242- }
218+ dds_rate = synthio_frequency_convert_scaled_to_dds ((uint64_t )frequency_scaled * waveform_length , sample_rate );
219+ if (note -> ring_frequency_scaled != 0 && note -> ring_waveform_buf .buf ) {
220+ ring_waveform = note -> ring_waveform_buf .buf ;
221+ ring_waveform_length = note -> ring_waveform_buf .len / 2 ;
222+ ring_dds_rate = synthio_frequency_convert_scaled_to_dds ((uint64_t )note -> ring_frequency_scaled * ring_waveform_length , sample_rate );
223+ uint32_t lim = ring_waveform_length << SYNTHIO_FREQUENCY_SHIFT ;
224+ if (ring_dds_rate > lim / 2 ) {
225+ ring_dds_rate = 0 ; // can't ring at that frequency
243226 }
244227 }
228+ }
245229
246- int synth_chan = synth -> channel_count ;
247- if (ring_dds_rate ) {
248- uint32_t lim = waveform_length << SYNTHIO_FREQUENCY_SHIFT ;
249- uint32_t accum = synth -> accum [chan ];
230+ int synth_chan = synth -> channel_count ;
231+ if (ring_dds_rate ) {
232+ uint32_t lim = waveform_length << SYNTHIO_FREQUENCY_SHIFT ;
233+ uint32_t accum = synth -> accum [chan ];
250234
251- if (dds_rate > lim / 2 ) {
252- // beyond nyquist, can't play note
253- continue ;
254- }
235+ if (dds_rate > lim / 2 ) {
236+ // beyond nyquist, can't play note
237+ return ;
238+ }
255239
256- // can happen if note waveform gets set mid-note, but the expensive modulo is usually avoided
240+ // can happen if note waveform gets set mid-note, but the expensive modulo is usually avoided
241+ if (accum > lim ) {
242+ accum %= lim ;
243+ }
244+
245+ int32_t ring_buffer [dur ];
246+ // first, fill with waveform
247+ for (uint16_t i = 0 ; i < dur ; i ++ ) {
248+ accum += dds_rate ;
249+ // because dds_rate is low enough, the subtraction is guaranteed to go back into range, no expensive modulo needed
257250 if (accum > lim ) {
258- accum % = lim ;
251+ accum - = lim ;
259252 }
253+ int16_t idx = accum >> SYNTHIO_FREQUENCY_SHIFT ;
254+ ring_buffer [i ] = waveform [idx ];
255+ }
256+ synth -> accum [chan ] = accum ;
260257
261- int32_t ring_buffer [dur ];
262- // first, fill with waveform
263- for (uint16_t i = 0 ; i < dur ; i ++ ) {
264- accum += dds_rate ;
265- // because dds_rate is low enough, the subtraction is guaranteed to go back into range, no expensive modulo needed
266- if (accum > lim ) {
267- accum -= lim ;
268- }
269- int16_t idx = accum >> SYNTHIO_FREQUENCY_SHIFT ;
270- ring_buffer [i ] = waveform [idx ];
271- }
272- synth -> accum [chan ] = accum ;
258+ // now modulate by ring and accumulate
259+ accum = synth -> ring_accum [chan ];
260+ lim = ring_waveform_length << SYNTHIO_FREQUENCY_SHIFT ;
273261
274- // now modulate by ring and accumulate
275- accum = synth -> ring_accum [chan ];
276- lim = ring_waveform_length << SYNTHIO_FREQUENCY_SHIFT ;
262+ // can happen if note waveform gets set mid-note, but the expensive modulo is usually avoided
263+ if (accum > lim ) {
264+ accum %= lim ;
265+ }
277266
278- // can happen if note waveform gets set mid-note, but the expensive modulo is usually avoided
267+ for (uint16_t i = 0 , j = 0 ; i < dur ; i ++ ) {
268+ accum += ring_dds_rate ;
269+ // because dds_rate is low enough, the subtraction is guaranteed to go back into range, no expensive modulo needed
279270 if (accum > lim ) {
280- accum % = lim ;
271+ accum - = lim ;
281272 }
282-
283- for (uint16_t i = 0 , j = 0 ; i < dur ; i ++ ) {
284- accum += ring_dds_rate ;
285- // because dds_rate is low enough, the subtraction is guaranteed to go back into range, no expensive modulo needed
286- if (accum > lim ) {
287- accum -= lim ;
288- }
289- int16_t idx = accum >> SYNTHIO_FREQUENCY_SHIFT ;
290- int16_t wi = (ring_waveform [idx ] * ring_buffer [i ]) / 32768 ;
291- for (int c = 0 ; c < synth_chan ; c ++ ) {
292- out_buffer32 [j ] += (wi * loudness [c ]) / 32768 ;
293- j ++ ;
294- }
273+ int16_t idx = accum >> SYNTHIO_FREQUENCY_SHIFT ;
274+ int16_t wi = (ring_waveform [idx ] * ring_buffer [i ]) / 32768 ;
275+ for (int c = 0 ; c < synth_chan ; c ++ ) {
276+ out_buffer32 [j ] += (wi * loudness [c ]) / 32768 ;
277+ j ++ ;
295278 }
296- synth -> ring_accum [chan ] = accum ;
297- } else {
298- uint32_t lim = waveform_length << SYNTHIO_FREQUENCY_SHIFT ;
299- uint32_t accum = synth -> accum [chan ];
279+ }
280+ synth -> ring_accum [chan ] = accum ;
281+ } else {
282+ uint32_t lim = waveform_length << SYNTHIO_FREQUENCY_SHIFT ;
283+ uint32_t accum = synth -> accum [chan ];
300284
301- if (dds_rate > lim / 2 ) {
302- // beyond nyquist, can't play note
303- continue ;
304- }
285+ if (dds_rate > lim / 2 ) {
286+ // beyond nyquist, can't play note
287+ return ;
288+ }
305289
306- // can happen if note waveform gets set mid-note, but the expensive modulo is usually avoided
290+ // can happen if note waveform gets set mid-note, but the expensive modulo is usually avoided
291+ if (accum > lim ) {
292+ accum %= lim ;
293+ }
294+
295+ for (uint16_t i = 0 , j = 0 ; i < dur ; i ++ ) {
296+ accum += dds_rate ;
297+ // because dds_rate is low enough, the subtraction is guaranteed to go back into range, no expensive modulo needed
307298 if (accum > lim ) {
308- accum % = lim ;
299+ accum - = lim ;
309300 }
310-
311- for (uint16_t i = 0 , j = 0 ; i < dur ; i ++ ) {
312- accum += dds_rate ;
313- // because dds_rate is low enough, the subtraction is guaranteed to go back into range, no expensive modulo needed
314- if (accum > lim ) {
315- accum -= lim ;
316- }
317- int16_t idx = accum >> SYNTHIO_FREQUENCY_SHIFT ;
318- int16_t wi = waveform [idx ];
319- for (int c = 0 ; c < synth_chan ; c ++ ) {
320- out_buffer32 [j ] += (wi * loudness [c ]) / 65536 ;
321- j ++ ;
322- }
301+ int16_t idx = accum >> SYNTHIO_FREQUENCY_SHIFT ;
302+ int16_t wi = waveform [idx ];
303+ for (int c = 0 ; c < synth_chan ; c ++ ) {
304+ out_buffer32 [j ] += (wi * loudness [c ]) / 65536 ;
305+ j ++ ;
323306 }
324- synth -> accum [chan ] = accum ;
325307 }
308+ synth -> accum [chan ] = accum ;
309+ }
310+ }
311+
312+ void synthio_synth_synthesize (synthio_synth_t * synth , uint8_t * * bufptr , uint32_t * buffer_length , uint8_t channel ) {
313+
314+ if (channel == synth -> other_channel ) {
315+ * buffer_length = synth -> last_buffer_length ;
316+ * bufptr = (uint8_t * )(synth -> buffers [synth -> other_buffer_index ] + channel );
317+ return ;
326318 }
327319
320+ synth -> buffer_index = !synth -> buffer_index ;
321+ synth -> other_channel = 1 - channel ;
322+ synth -> other_buffer_index = synth -> buffer_index ;
323+
324+ uint16_t dur = MIN (SYNTHIO_MAX_DUR , synth -> span .dur );
325+ synth -> span .dur -= dur ;
326+
327+ int32_t out_buffer32 [dur * synth -> channel_count ];
328+
329+ memset (out_buffer32 , 0 , sizeof (out_buffer32 ));
330+ for (int chan = 0 ; chan < CIRCUITPY_SYNTHIO_MAX_CHANNELS ; chan ++ ) {
331+ synth_note_into_buffer (synth , chan , out_buffer32 , dur );
332+ }
333+
334+
328335 int16_t * out_buffer16 = (int16_t * )(void * )synth -> buffers [synth -> buffer_index ];
329336
330337 // mix down audio
@@ -358,8 +365,7 @@ bool synthio_synth_deinited(synthio_synth_t *synth) {
358365}
359366
360367void synthio_synth_deinit (synthio_synth_t * synth ) {
361- m_del (uint8_t , synth -> buffers [0 ], synth -> buffer_length );
362- m_del (uint8_t , synth -> buffers [1 ], synth -> buffer_length );
368+ synth -> filter_buffer = NULL ;
363369 synth -> buffers [0 ] = NULL ;
364370 synth -> buffers [1 ] = NULL ;
365371}
@@ -374,15 +380,19 @@ mp_obj_t synthio_synth_envelope_get(synthio_synth_t *synth) {
374380}
375381
376382void synthio_synth_init (synthio_synth_t * synth , uint32_t sample_rate , int channel_count , mp_obj_t waveform_obj , mp_obj_t filter_obj , mp_obj_t envelope_obj ) {
383+ synthio_synth_parse_waveform (& synth -> waveform_bufinfo , waveform_obj );
384+ synthio_synth_parse_filter (& synth -> filter_bufinfo , filter_obj );
377385 mp_arg_validate_int_range (channel_count , 1 , 2 , MP_QSTR_channel_count );
378386 synth -> buffer_length = SYNTHIO_MAX_DUR * SYNTHIO_BYTES_PER_SAMPLE * channel_count ;
379387 synth -> buffers [0 ] = m_malloc (synth -> buffer_length , false);
380388 synth -> buffers [1 ] = m_malloc (synth -> buffer_length , false);
389+ if (synth -> filter_bufinfo .len ) {
390+ synth -> filter_buffer_length = (synth -> filter_bufinfo .len + SYNTHIO_MAX_DUR ) * channel_count * sizeof (int32_t );
391+ synth -> filter_buffer = m_malloc (synth -> filter_buffer_length , false);
392+ }
381393 synth -> channel_count = channel_count ;
382394 synth -> other_channel = -1 ;
383395 synth -> waveform_obj = waveform_obj ;
384- synthio_synth_parse_waveform (& synth -> waveform_bufinfo , waveform_obj );
385- synthio_synth_parse_filter (& synth -> filter_bufinfo , filter_obj );
386396 synth -> sample_rate = sample_rate ;
387397 synthio_synth_envelope_set (synth , envelope_obj );
388398
0 commit comments