Skip to content

Commit 13a8fb9

Browse files
authored
Merge pull request #10906 from relic-se/audiomixer-samd-fix
Fix `audiomixer.Mixer` regressions on SAMD51
2 parents 358a334 + 873e3c2 commit 13a8fb9

2 files changed

Lines changed: 39 additions & 40 deletions

File tree

shared-module/audiomixer/Mixer.c

Lines changed: 38 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -92,23 +92,23 @@ 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[2]) {
95+
static inline uint32_t mult16signed(uint32_t val, int32_t lomul, int32_t himul) {
9696
#if (defined(__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1))
97-
mul[0] <<= 16;
98-
mul[1] <<= 16;
97+
lomul <<= 16;
98+
himul <<= 16;
9999
int32_t hi, lo;
100100
enum { bits = 16 }; // saturate to 16 bits
101101
enum { shift = 15 }; // shift is done automatically
102-
__asm__ volatile ("smulwb %0, %1, %2" : "=r" (lo) : "r" (mul[0]), "r" (val));
103-
__asm__ volatile ("smulwt %0, %1, %2" : "=r" (hi) : "r" (mul[1]), "r" (val));
102+
__asm__ volatile ("smulwb %0, %1, %2" : "=r" (lo) : "r" (lomul), "r" (val));
103+
__asm__ volatile ("smulwt %0, %1, %2" : "=r" (hi) : "r" (himul), "r" (val));
104104
__asm__ volatile ("ssat %0, %1, %2, asr %3" : "=r" (lo) : "I" (bits), "r" (lo), "I" (shift));
105105
__asm__ volatile ("ssat %0, %1, %2, asr %3" : "=r" (hi) : "I" (bits), "r" (hi), "I" (shift));
106106
__asm__ volatile ("pkhbt %0, %1, %2, lsl #16" : "=r" (val) : "r" (lo), "r" (hi)); // pack
107107
return val;
108108
#else
109109
uint32_t result = 0;
110110
for (int8_t i = 0; i < 2; i++) {
111-
float mod_mul = (float)mul[i] / (float)((1 << 15) - 1);
111+
float mod_mul = (float)(i ? himul : lomul) / (float)((1 << 15) - 1);
112112
int16_t ai = (val >> (sizeof(uint16_t) * 8 * i));
113113
int32_t intermediate = (int32_t)(ai * mod_mul);
114114
if (intermediate > SHRT_MAX) {
@@ -156,23 +156,21 @@ static inline uint32_t pack8(uint32_t val) {
156156
}
157157

158158
static inline uint32_t copy16lsb(uint32_t val) {
159+
#if (defined(__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1))
160+
return __PKHBT(val, val, 16);
161+
#else
159162
val &= 0x0000ffff;
160163
return val | (val << 16);
164+
#endif
161165
}
162166

163167
static inline uint32_t copy16msb(uint32_t val) {
168+
#if (defined(__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1))
169+
return __PKHTB(val, val, 16);
170+
#else
164171
val &= 0xffff0000;
165172
return val | (val >> 16);
166-
}
167-
168-
static inline uint32_t copy8lsb(uint32_t val) {
169-
val &= 0x00ff;
170-
return val | (val << 8);
171-
}
172-
173-
static inline uint32_t copy8msb(uint32_t val) {
174-
val &= 0xff00;
175-
return val | (val >> 8);
173+
#endif
176174
}
177175

178176
#define ALMOST_ONE (MICROPY_FLOAT_CONST(32767.) / 32768)
@@ -228,16 +226,17 @@ static void mix_down_one_voice(audiomixer_mixer_obj_t *self,
228226
uint16_t left_panning_scaled = 32768, right_panning_scaled = 32768;
229227
if (MP_LIKELY(self->base.channel_count == 2)) {
230228
if (panning >= 0) {
231-
right_panning_scaled = 32767 - panning;
229+
left_panning_scaled = 32767 - panning;
232230
} else {
233-
left_panning_scaled = 32767 + panning;
231+
right_panning_scaled = 32767 + panning;
234232
}
235233
}
236234

237-
int32_t loudness[2] = { level, level };
235+
int32_t lo_level = level;
236+
int32_t hi_level = level;
238237
if (MP_LIKELY(self->base.channel_count == 2)) {
239-
loudness[0] = (left_panning_scaled * loudness[0]) >> 15;
240-
loudness[1] = (right_panning_scaled * loudness[1]) >> 15;
238+
lo_level = (left_panning_scaled * lo_level) >> 15;
239+
hi_level = (right_panning_scaled * hi_level) >> 15;
241240
}
242241

243242
// First active voice gets copied over verbatim.
@@ -247,28 +246,28 @@ static void mix_down_one_voice(audiomixer_mixer_obj_t *self,
247246
if (MP_LIKELY(self->base.channel_count == sample->channel_count)) {
248247
for (uint32_t i = 0; i < n; i++) {
249248
uint32_t v = src[i];
250-
word_buffer[i] = mult16signed(v, loudness);
249+
word_buffer[i] = mult16signed(v, lo_level, hi_level);
251250
}
252251
} else {
253252
for (uint32_t i = 0; i < n; i += 2) {
254253
uint32_t v = src[i >> 1];
255-
word_buffer[i] = mult16signed(copy16lsb(v), loudness);
256-
word_buffer[i + 1] = mult16signed(copy16msb(v), loudness);
254+
word_buffer[i] = mult16signed(copy16lsb(v), lo_level, hi_level);
255+
word_buffer[i + 1] = mult16signed(copy16msb(v), lo_level, hi_level);
257256
}
258257
}
259258
} else {
260259
if (MP_LIKELY(self->base.channel_count == sample->channel_count)) {
261260
for (uint32_t i = 0; i < n; i++) {
262261
uint32_t v = src[i];
263262
v = tosigned16(v);
264-
word_buffer[i] = mult16signed(v, loudness);
263+
word_buffer[i] = mult16signed(v, lo_level, hi_level);
265264
}
266265
} else {
267266
for (uint32_t i = 0; i + 1 < n; i += 2) {
268267
uint32_t v = src[i >> 1];
269268
v = tosigned16(v);
270-
word_buffer[i] = mult16signed(copy16lsb(v), loudness);
271-
word_buffer[i + 1] = mult16signed(copy16msb(v), loudness);
269+
word_buffer[i] = mult16signed(copy16lsb(v), lo_level, hi_level);
270+
word_buffer[i + 1] = mult16signed(copy16msb(v), lo_level, hi_level);
272271
}
273272
}
274273
}
@@ -281,7 +280,7 @@ static void mix_down_one_voice(audiomixer_mixer_obj_t *self,
281280
if (MP_LIKELY(!self->base.samples_signed)) {
282281
word = tosigned16(word);
283282
}
284-
word = mult16signed(word, loudness);
283+
word = mult16signed(word, lo_level, hi_level);
285284
hword_buffer[i] = pack8(word);
286285
}
287286
} else {
@@ -290,8 +289,8 @@ static void mix_down_one_voice(audiomixer_mixer_obj_t *self,
290289
if (MP_LIKELY(!self->base.samples_signed)) {
291290
word = tosigned16(word);
292291
}
293-
hword_buffer[i] = pack8(mult16signed(copy16lsb(word), loudness));
294-
hword_buffer[i + 1] = pack8(mult16signed(copy16msb(word), loudness));
292+
hword_buffer[i] = pack8(mult16signed(copy16lsb(word), lo_level, hi_level));
293+
hword_buffer[i + 1] = pack8(mult16signed(copy16msb(word), lo_level, hi_level));
295294
}
296295
}
297296
}
@@ -301,28 +300,28 @@ static void mix_down_one_voice(audiomixer_mixer_obj_t *self,
301300
if (MP_LIKELY(self->base.channel_count == sample->channel_count)) {
302301
for (uint32_t i = 0; i < n; i++) {
303302
uint32_t word = src[i];
304-
word_buffer[i] = add16signed(mult16signed(word, loudness), word_buffer[i]);
303+
word_buffer[i] = add16signed(mult16signed(word, lo_level, hi_level), word_buffer[i]);
305304
}
306305
} else {
307306
for (uint32_t i = 0; i + 1 < n; i += 2) {
308307
uint32_t word = src[i >> 1];
309-
word_buffer[i] = add16signed(mult16signed(copy16lsb(word), loudness), word_buffer[i]);
310-
word_buffer[i + 1] = add16signed(mult16signed(copy16msb(word), loudness), word_buffer[i + 1]);
308+
word_buffer[i] = add16signed(mult16signed(copy16lsb(word), lo_level, hi_level), word_buffer[i]);
309+
word_buffer[i + 1] = add16signed(mult16signed(copy16msb(word), lo_level, hi_level), word_buffer[i + 1]);
311310
}
312311
}
313312
} else {
314313
if (MP_LIKELY(self->base.channel_count == sample->channel_count)) {
315314
for (uint32_t i = 0; i < n; i++) {
316315
uint32_t word = src[i];
317316
word = tosigned16(word);
318-
word_buffer[i] = add16signed(mult16signed(word, loudness), word_buffer[i]);
317+
word_buffer[i] = add16signed(mult16signed(word, lo_level, hi_level), word_buffer[i]);
319318
}
320319
} else {
321320
for (uint32_t i = 0; i + 1 < n; i += 2) {
322321
uint32_t word = src[i >> 1];
323322
word = tosigned16(word);
324-
word_buffer[i] = add16signed(mult16signed(copy16lsb(word), loudness), word_buffer[i]);
325-
word_buffer[i + 1] = add16signed(mult16signed(copy16msb(word), loudness), word_buffer[i + 1]);
323+
word_buffer[i] = add16signed(mult16signed(copy16lsb(word), lo_level, hi_level), word_buffer[i]);
324+
word_buffer[i + 1] = add16signed(mult16signed(copy16msb(word), lo_level, hi_level), word_buffer[i + 1]);
326325
}
327326
}
328327
}
@@ -335,7 +334,7 @@ static void mix_down_one_voice(audiomixer_mixer_obj_t *self,
335334
if (MP_LIKELY(!self->base.samples_signed)) {
336335
word = tosigned16(word);
337336
}
338-
word = mult16signed(word, loudness);
337+
word = mult16signed(word, lo_level, hi_level);
339338
word = add16signed(word, unpack8(hword_buffer[i]));
340339
hword_buffer[i] = pack8(word);
341340
}
@@ -345,8 +344,8 @@ static void mix_down_one_voice(audiomixer_mixer_obj_t *self,
345344
if (MP_LIKELY(!self->base.samples_signed)) {
346345
word = tosigned16(word);
347346
}
348-
hword_buffer[i] = pack8(add16signed(mult16signed(copy16lsb(word), loudness), unpack8(hword_buffer[i])));
349-
hword_buffer[i + 1] = pack8(add16signed(mult16signed(copy16msb(word), loudness), unpack8(hword_buffer[i + 1])));
347+
hword_buffer[i] = pack8(add16signed(mult16signed(copy16lsb(word), lo_level, hi_level), unpack8(hword_buffer[i])));
348+
hword_buffer[i + 1] = pack8(add16signed(mult16signed(copy16msb(word), lo_level, hi_level), unpack8(hword_buffer[i + 1])));
350349
}
351350
}
352351
}

shared-module/audiomixer/MixerVoice.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ void common_hal_audiomixer_mixervoice_set_panning(audiomixer_mixervoice_obj_t *s
5151
#if CIRCUITPY_SYNTHIO
5252
synthio_block_assign_slot(arg, &self->panning, MP_QSTR_panning);
5353
#else
54-
self->panning = (uint16_t)(mp_arg_validate_obj_float_range(arg, -1, 1, MP_QSTR_panning) * ((1 << 15) - 1));
54+
self->panning = (int16_t)(mp_arg_validate_obj_float_range(arg, -1, 1, MP_QSTR_panning) * ((1 << 15) - 1));
5555
#endif
5656
}
5757

0 commit comments

Comments
 (0)