@@ -92,22 +92,22 @@ static inline uint32_t add16signed(uint32_t a, uint32_t b) {
9292}
9393
9494__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 ] ) {
9696 #if (defined(__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1 ))
9797 mul <<= 16 ;
9898 int32_t hi , lo ;
9999 enum { bits = 16 }; // saturate to 16 bits
100100 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 ));
103103 asm volatile ("ssat %0, %1, %2, asr %3" : "=r" (lo ) : "I" (bits ), "r" (lo ), "I" (shift ));
104104 asm volatile ("ssat %0, %1, %2, asr %3" : "=r" (hi ) : "I" (bits ), "r" (hi ), "I" (shift ));
105105 asm volatile ("pkhbt %0, %1, %2, lsl #16" : "=r" (val ) : "r" (lo ), "r" (hi )); // pack
106106 return val ;
107107 #else
108108 uint32_t result = 0 ;
109- float mod_mul = (float )mul / (float )((1 << 15 ) - 1 );
110109 for (int8_t i = 0 ; i < 2 ; i ++ ) {
110+ float mod_mul = (float )mul [i ] / (float )((1 << 15 ) - 1 );
111111 int16_t ai = (val >> (sizeof (uint16_t ) * 8 * i ));
112112 int32_t intermediate = (int32_t )(ai * mod_mul );
113113 if (intermediate > SHRT_MAX ) {
@@ -174,6 +174,8 @@ static inline uint32_t copy8msb(uint32_t val) {
174174 return val | (val >> 8 );
175175}
176176
177+ #define ALMOST_ONE (MICROPY_FLOAT_CONST(32767.) / 32768)
178+
177179static void mix_down_one_voice (audiomixer_mixer_obj_t * self ,
178180 audiomixer_mixervoice_obj_t * voice , bool voices_active ,
179181 uint32_t * word_buffer , uint32_t length ) {
@@ -210,6 +212,7 @@ static void mix_down_one_voice(audiomixer_mixer_obj_t *self,
210212 // Get the current level from the BlockInput. These may change at run time so you need to do bounds checking if required.
211213 shared_bindings_synthio_lfo_tick (self -> base .sample_rate , n / self -> base .channel_count );
212214 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 );
213216 #else
214217 uint32_t n ;
215218 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,
218221 n = MIN (voice -> buffer_length << 1 , length );
219222 }
220223 uint16_t level = voice -> level ;
224+ int16_t panning = voice -> panning ;
221225 #endif
222226
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+
223242 // First active voice gets copied over verbatim.
224243 if (!voices_active ) {
225244 if (MP_LIKELY (self -> base .bits_per_sample == 16 )) {
226245 if (MP_LIKELY (self -> base .samples_signed )) {
227246 if (MP_LIKELY (self -> base .channel_count == sample -> channel_count )) {
228247 for (uint32_t i = 0 ; i < n ; i ++ ) {
229248 uint32_t v = src [i ];
230- word_buffer [i ] = mult16signed (v , level );
249+ word_buffer [i ] = mult16signed (v , loudness );
231250 }
232251 } else {
233252 for (uint32_t i = 0 ; i < n ; i += 2 ) {
234253 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 );
238256 }
239257 }
240258 } else {
241259 if (MP_LIKELY (self -> base .channel_count == sample -> channel_count )) {
242260 for (uint32_t i = 0 ; i < n ; i ++ ) {
243261 uint32_t v = src [i ];
244262 v = tosigned16 (v );
245- word_buffer [i ] = mult16signed (v , level );
263+ word_buffer [i ] = mult16signed (v , loudness );
246264 }
247265 } else {
248266 for (uint32_t i = 0 ; i + 1 < n ; i += 2 ) {
249267 uint32_t v = src [i >> 1 ];
250268 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 );
254271 }
255272 }
256273 }
@@ -263,7 +280,7 @@ static void mix_down_one_voice(audiomixer_mixer_obj_t *self,
263280 if (MP_LIKELY (!self -> base .samples_signed )) {
264281 word = tosigned16 (word );
265282 }
266- word = mult16signed (word , level );
283+ word = mult16signed (word , loudness );
267284 hword_buffer [i ] = pack8 (word );
268285 }
269286 } else {
@@ -272,10 +289,8 @@ static void mix_down_one_voice(audiomixer_mixer_obj_t *self,
272289 if (MP_LIKELY (!self -> base .samples_signed )) {
273290 word = tosigned16 (word );
274291 }
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 ));
279294 }
280295 }
281296 }
@@ -285,30 +300,28 @@ static void mix_down_one_voice(audiomixer_mixer_obj_t *self,
285300 if (MP_LIKELY (self -> base .channel_count == sample -> channel_count )) {
286301 for (uint32_t i = 0 ; i < n ; i ++ ) {
287302 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 ]);
289304 }
290305 } else {
291306 for (uint32_t i = 0 ; i + 1 < n ; i += 2 ) {
292307 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 ]);
296310 }
297311 }
298312 } else {
299313 if (MP_LIKELY (self -> base .channel_count == sample -> channel_count )) {
300314 for (uint32_t i = 0 ; i < n ; i ++ ) {
301315 uint32_t word = src [i ];
302316 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 ]);
304318 }
305319 } else {
306320 for (uint32_t i = 0 ; i + 1 < n ; i += 2 ) {
307321 uint32_t word = src [i >> 1 ];
308322 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 ]);
312325 }
313326 }
314327 }
@@ -321,7 +334,7 @@ static void mix_down_one_voice(audiomixer_mixer_obj_t *self,
321334 if (MP_LIKELY (!self -> base .samples_signed )) {
322335 word = tosigned16 (word );
323336 }
324- word = mult16signed (word , level );
337+ word = mult16signed (word , loudness );
325338 word = add16signed (word , unpack8 (hword_buffer [i ]));
326339 hword_buffer [i ] = pack8 (word );
327340 }
@@ -331,9 +344,8 @@ static void mix_down_one_voice(audiomixer_mixer_obj_t *self,
331344 if (MP_LIKELY (!self -> base .samples_signed )) {
332345 word = tosigned16 (word );
333346 }
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 ])));
337349 }
338350 }
339351 }
0 commit comments