@@ -92,22 +92,22 @@ static inline uint32_t add16signed(uint32_t a, uint32_t b) {
92
92
}
93
93
94
94
__attribute__((always_inline ))
95
- static inline uint32_t mult16signed (uint32_t val , int32_t mul ) {
95
+ static inline uint32_t mult16signed (uint32_t val , int32_t mul [ 2 ] ) {
96
96
#if (defined(__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1 ))
97
97
mul <<= 16 ;
98
98
int32_t hi , lo ;
99
99
enum { bits = 16 }; // saturate to 16 bits
100
100
enum { shift = 15 }; // shift is done automatically
101
- asm volatile ("smulwb %0, %1, %2" : "=r" (lo ) : "r" (mul ), "r" (val ));
102
- asm volatile ("smulwt %0, %1, %2" : "=r" (hi ) : "r" (mul ), "r" (val ));
101
+ asm volatile ("smulwb %0, %1, %2" : "=r" (lo ) : "r" (mul [ 0 ] ), "r" (val ));
102
+ asm volatile ("smulwt %0, %1, %2" : "=r" (hi ) : "r" (mul [ 1 ] ), "r" (val ));
103
103
asm volatile ("ssat %0, %1, %2, asr %3" : "=r" (lo ) : "I" (bits ), "r" (lo ), "I" (shift ));
104
104
asm volatile ("ssat %0, %1, %2, asr %3" : "=r" (hi ) : "I" (bits ), "r" (hi ), "I" (shift ));
105
105
asm volatile ("pkhbt %0, %1, %2, lsl #16" : "=r" (val ) : "r" (lo ), "r" (hi )); // pack
106
106
return val ;
107
107
#else
108
108
uint32_t result = 0 ;
109
- float mod_mul = (float )mul / (float )((1 << 15 ) - 1 );
110
109
for (int8_t i = 0 ; i < 2 ; i ++ ) {
110
+ float mod_mul = (float )mul [i ] / (float )((1 << 15 ) - 1 );
111
111
int16_t ai = (val >> (sizeof (uint16_t ) * 8 * i ));
112
112
int32_t intermediate = (int32_t )(ai * mod_mul );
113
113
if (intermediate > SHRT_MAX ) {
@@ -174,6 +174,8 @@ static inline uint32_t copy8msb(uint32_t val) {
174
174
return val | (val >> 8 );
175
175
}
176
176
177
+ #define ALMOST_ONE (MICROPY_FLOAT_CONST(32767.) / 32768)
178
+
177
179
static void mix_down_one_voice (audiomixer_mixer_obj_t * self ,
178
180
audiomixer_mixervoice_obj_t * voice , bool voices_active ,
179
181
uint32_t * word_buffer , uint32_t length ) {
@@ -210,6 +212,7 @@ static void mix_down_one_voice(audiomixer_mixer_obj_t *self,
210
212
// Get the current level from the BlockInput. These may change at run time so you need to do bounds checking if required.
211
213
shared_bindings_synthio_lfo_tick (self -> base .sample_rate , n / self -> base .channel_count );
212
214
uint16_t level = (uint16_t )(synthio_block_slot_get_limited (& voice -> level , MICROPY_FLOAT_CONST (0.0 ), MICROPY_FLOAT_CONST (1.0 )) * (1 << 15 ));
215
+ int16_t panning = synthio_block_slot_get_scaled (& voice -> panning , - ALMOST_ONE , ALMOST_ONE );
213
216
#else
214
217
uint32_t n ;
215
218
if (MP_LIKELY (self -> base .channel_count == sample -> channel_count )) {
@@ -218,39 +221,53 @@ static void mix_down_one_voice(audiomixer_mixer_obj_t *self,
218
221
n = MIN (voice -> buffer_length << 1 , length );
219
222
}
220
223
uint16_t level = voice -> level ;
224
+ int16_t panning = voice -> panning ;
221
225
#endif
222
226
227
+ uint16_t left_panning_scaled = 32768 , right_panning_scaled = 32768 ;
228
+ if (MP_LIKELY (self -> base .channel_count == 2 )) {
229
+ if (panning >= 0 ) {
230
+ right_panning_scaled = 32767 - panning ;
231
+ } else {
232
+ left_panning_scaled = 32767 + panning ;
233
+ }
234
+ }
235
+
236
+ int32_t loudness [2 ] = { level , level };
237
+ if (MP_LIKELY (self -> base .channel_count == 2 )) {
238
+ loudness [0 ] = (left_panning_scaled * loudness [0 ]) >> 15 ;
239
+ loudness [1 ] = (right_panning_scaled * loudness [1 ]) >> 15 ;
240
+ }
241
+
223
242
// First active voice gets copied over verbatim.
224
243
if (!voices_active ) {
225
244
if (MP_LIKELY (self -> base .bits_per_sample == 16 )) {
226
245
if (MP_LIKELY (self -> base .samples_signed )) {
227
246
if (MP_LIKELY (self -> base .channel_count == sample -> channel_count )) {
228
247
for (uint32_t i = 0 ; i < n ; i ++ ) {
229
248
uint32_t v = src [i ];
230
- word_buffer [i ] = mult16signed (v , level );
249
+ word_buffer [i ] = mult16signed (v , loudness );
231
250
}
232
251
} else {
233
252
for (uint32_t i = 0 ; i < n ; i += 2 ) {
234
253
uint32_t v = src [i >> 1 ];
235
- v = mult16signed (v , level );
236
- word_buffer [i ] = copy16lsb (v );
237
- word_buffer [i + 1 ] = copy16msb (v );
254
+ word_buffer [i ] = mult16signed (copy16lsb (v ), loudness );
255
+ word_buffer [i + 1 ] = mult16signed (copy16msb (v ), loudness );
238
256
}
239
257
}
240
258
} else {
241
259
if (MP_LIKELY (self -> base .channel_count == sample -> channel_count )) {
242
260
for (uint32_t i = 0 ; i < n ; i ++ ) {
243
261
uint32_t v = src [i ];
244
262
v = tosigned16 (v );
245
- word_buffer [i ] = mult16signed (v , level );
263
+ word_buffer [i ] = mult16signed (v , loudness );
246
264
}
247
265
} else {
248
266
for (uint32_t i = 0 ; i + 1 < n ; i += 2 ) {
249
267
uint32_t v = src [i >> 1 ];
250
268
v = tosigned16 (v );
251
- v = mult16signed (v , level );
252
- word_buffer [i ] = copy16lsb (v );
253
- word_buffer [i + 1 ] = copy16msb (v );
269
+ word_buffer [i ] = mult16signed (copy16lsb (v ), loudness );
270
+ word_buffer [i + 1 ] = mult16signed (copy16msb (v ), loudness );
254
271
}
255
272
}
256
273
}
@@ -263,7 +280,7 @@ static void mix_down_one_voice(audiomixer_mixer_obj_t *self,
263
280
if (MP_LIKELY (!self -> base .samples_signed )) {
264
281
word = tosigned16 (word );
265
282
}
266
- word = mult16signed (word , level );
283
+ word = mult16signed (word , loudness );
267
284
hword_buffer [i ] = pack8 (word );
268
285
}
269
286
} else {
@@ -272,10 +289,8 @@ static void mix_down_one_voice(audiomixer_mixer_obj_t *self,
272
289
if (MP_LIKELY (!self -> base .samples_signed )) {
273
290
word = tosigned16 (word );
274
291
}
275
- word = mult16signed (word , level );
276
- word = pack8 (word );
277
- hword_buffer [i ] = copy8lsb (word );
278
- hword_buffer [i + 1 ] = copy8msb (word );
292
+ hword_buffer [i ] = pack8 (mult16signed (copy16lsb (word ), loudness ));
293
+ hword_buffer [i + 1 ] = pack8 (mult16signed (copy16msb (word ), loudness ));
279
294
}
280
295
}
281
296
}
@@ -285,30 +300,28 @@ static void mix_down_one_voice(audiomixer_mixer_obj_t *self,
285
300
if (MP_LIKELY (self -> base .channel_count == sample -> channel_count )) {
286
301
for (uint32_t i = 0 ; i < n ; i ++ ) {
287
302
uint32_t word = src [i ];
288
- word_buffer [i ] = add16signed (mult16signed (word , level ), word_buffer [i ]);
303
+ word_buffer [i ] = add16signed (mult16signed (word , loudness ), word_buffer [i ]);
289
304
}
290
305
} else {
291
306
for (uint32_t i = 0 ; i + 1 < n ; i += 2 ) {
292
307
uint32_t word = src [i >> 1 ];
293
- word = mult16signed (word , level );
294
- word_buffer [i ] = add16signed (copy16lsb (word ), word_buffer [i ]);
295
- word_buffer [i + 1 ] = add16signed (copy16msb (word ), word_buffer [i + 1 ]);
308
+ word_buffer [i ] = add16signed (mult16signed (copy16lsb (word ), loudness ), word_buffer [i ]);
309
+ word_buffer [i + 1 ] = add16signed (mult16signed (copy16msb (word ), loudness ), word_buffer [i + 1 ]);
296
310
}
297
311
}
298
312
} else {
299
313
if (MP_LIKELY (self -> base .channel_count == sample -> channel_count )) {
300
314
for (uint32_t i = 0 ; i < n ; i ++ ) {
301
315
uint32_t word = src [i ];
302
316
word = tosigned16 (word );
303
- word_buffer [i ] = add16signed (mult16signed (word , level ), word_buffer [i ]);
317
+ word_buffer [i ] = add16signed (mult16signed (word , loudness ), word_buffer [i ]);
304
318
}
305
319
} else {
306
320
for (uint32_t i = 0 ; i + 1 < n ; i += 2 ) {
307
321
uint32_t word = src [i >> 1 ];
308
322
word = tosigned16 (word );
309
- word = mult16signed (word , level );
310
- word_buffer [i ] = add16signed (copy16lsb (word ), word_buffer [i ]);
311
- word_buffer [i + 1 ] = add16signed (copy16msb (word ), word_buffer [i + 1 ]);
323
+ word_buffer [i ] = add16signed (mult16signed (copy16lsb (word ), loudness ), word_buffer [i ]);
324
+ word_buffer [i + 1 ] = add16signed (mult16signed (copy16msb (word ), loudness ), word_buffer [i + 1 ]);
312
325
}
313
326
}
314
327
}
@@ -321,7 +334,7 @@ static void mix_down_one_voice(audiomixer_mixer_obj_t *self,
321
334
if (MP_LIKELY (!self -> base .samples_signed )) {
322
335
word = tosigned16 (word );
323
336
}
324
- word = mult16signed (word , level );
337
+ word = mult16signed (word , loudness );
325
338
word = add16signed (word , unpack8 (hword_buffer [i ]));
326
339
hword_buffer [i ] = pack8 (word );
327
340
}
@@ -331,9 +344,8 @@ static void mix_down_one_voice(audiomixer_mixer_obj_t *self,
331
344
if (MP_LIKELY (!self -> base .samples_signed )) {
332
345
word = tosigned16 (word );
333
346
}
334
- word = mult16signed (word , level );
335
- hword_buffer [i ] = pack8 (add16signed (copy16lsb (word ), unpack8 (hword_buffer [i ])));
336
- hword_buffer [i + 1 ] = pack8 (add16signed (copy16msb (word ), unpack8 (hword_buffer [i + 1 ])));
347
+ hword_buffer [i ] = pack8 (add16signed (mult16signed (copy16lsb (word ), loudness ), unpack8 (hword_buffer [i ])));
348
+ hword_buffer [i + 1 ] = pack8 (add16signed (mult16signed (copy16msb (word ), loudness ), unpack8 (hword_buffer [i + 1 ])));
337
349
}
338
350
}
339
351
}
0 commit comments