@@ -171,160 +171,167 @@ int16_t mix_down_sample(int32_t sample) {
171
171
return sample ;
172
172
}
173
173
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 ];
175
176
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 ;
179
179
return ;
180
180
}
181
181
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
+ }
188
187
189
188
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
- }
199
189
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 ;
204
217
}
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
243
226
}
244
227
}
228
+ }
245
229
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 ];
250
234
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
+ }
255
239
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
257
250
if (accum > lim ) {
258
- accum % = lim ;
251
+ accum - = lim ;
259
252
}
253
+ int16_t idx = accum >> SYNTHIO_FREQUENCY_SHIFT ;
254
+ ring_buffer [i ] = waveform [idx ];
255
+ }
256
+ synth -> accum [chan ] = accum ;
260
257
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 ;
273
261
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
+ }
277
266
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
279
270
if (accum > lim ) {
280
- accum % = lim ;
271
+ accum - = lim ;
281
272
}
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 ++ ;
295
278
}
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 ];
300
284
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
+ }
305
289
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
307
298
if (accum > lim ) {
308
- accum % = lim ;
299
+ accum - = lim ;
309
300
}
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 ++ ;
323
306
}
324
- synth -> accum [chan ] = accum ;
325
307
}
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 ;
326
318
}
327
319
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
+
328
335
int16_t * out_buffer16 = (int16_t * )(void * )synth -> buffers [synth -> buffer_index ];
329
336
330
337
// mix down audio
@@ -358,8 +365,7 @@ bool synthio_synth_deinited(synthio_synth_t *synth) {
358
365
}
359
366
360
367
void 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 ;
363
369
synth -> buffers [0 ] = NULL ;
364
370
synth -> buffers [1 ] = NULL ;
365
371
}
@@ -374,15 +380,19 @@ mp_obj_t synthio_synth_envelope_get(synthio_synth_t *synth) {
374
380
}
375
381
376
382
void 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 );
377
385
mp_arg_validate_int_range (channel_count , 1 , 2 , MP_QSTR_channel_count );
378
386
synth -> buffer_length = SYNTHIO_MAX_DUR * SYNTHIO_BYTES_PER_SAMPLE * channel_count ;
379
387
synth -> buffers [0 ] = m_malloc (synth -> buffer_length , false);
380
388
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
+ }
381
393
synth -> channel_count = channel_count ;
382
394
synth -> other_channel = -1 ;
383
395
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 );
386
396
synth -> sample_rate = sample_rate ;
387
397
synthio_synth_envelope_set (synth , envelope_obj );
388
398
0 commit comments