@@ -61,6 +61,7 @@ void common_hal_audioio_mixer_construct(audioio_mixer_obj_t* self,
6161
6262 for (uint8_t i = 0 ; i < self -> voice_count ; i ++ ) {
6363 self -> voice [i ].sample = NULL ;
64+ self -> voice [i ].gain = ((1 <<15 )- 1 );
6465 }
6566}
6667
@@ -131,6 +132,11 @@ void audioio_mixer_reset_buffer(audioio_mixer_obj_t* self,
131132 }
132133}
133134
135+ void common_hal_audioio_mixer_set_gain (audioio_mixer_obj_t * self , uint8_t voice , float gain ) {
136+ audioio_mixer_voice_t * v = & self -> voice [voice ];
137+ v -> gain = gain * ((1 << 15 )- 1 );
138+ }
139+
134140uint32_t add8signed (uint32_t a , uint32_t b ) {
135141 #if (defined (__ARM_FEATURE_DSP ) && (__ARM_FEATURE_DSP == 1 ))
136142 return __QADD8 (a , b );
@@ -215,6 +221,68 @@ uint32_t add16unsigned(uint32_t a, uint32_t b) {
215221 #endif
216222}
217223
224+ //TODO:
225+ static inline uint32_t mult8unsigned (uint32_t val , int32_t mul ) {
226+ #if (defined (__ARM_FEATURE_DSP ) && (__ARM_FEATURE_DSP == 1 ))
227+ return val ;
228+ val = __USUB8 (val , 0x80808080 );
229+ #else
230+ uint32_t result = 0 ;
231+ for (int8_t i = 0 ; i < 4 ; i ++ ) {
232+ int8_t ai = (val >> (sizeof (uint8_t ) * 8 * i )) - 128 ;
233+ }
234+ return result ;
235+ #endif
236+ }
237+
238+ //TODO:
239+ static inline uint32_t mult8signed (uint32_t val , int32_t mul ) {
240+ #if (defined (__ARM_FEATURE_DSP ) && (__ARM_FEATURE_DSP == 1 ))
241+ return val ;
242+ #else
243+ uint32_t result = 0 ;
244+ for (int8_t i = 0 ; i < 4 ; i ++ ) {
245+ int8_t ai = val >> (sizeof (int8_t ) * 8 * i );
246+ }
247+ return result ;
248+ #endif
249+ }
250+
251+ //TODO:
252+ static inline uint32_t mult16unsigned (uint32_t val , int32_t mul ) {
253+ #if (defined (__ARM_FEATURE_DSP ) && (__ARM_FEATURE_DSP == 1 ))
254+ return val ;
255+ val = __USUB16 (val , 0x80008000 );
256+ #else
257+ uint32_t result = 0 ;
258+ for (int8_t i = 0 ; i < 2 ; i ++ ) {
259+ int16_t ai = (val >> (sizeof (uint16_t ) * 8 * i )) - 0x8000 ;
260+ }
261+ return result ;
262+ #endif
263+ }
264+
265+ static inline uint32_t mult16signed (uint32_t val , int32_t mul ) {
266+ #if (defined (__ARM_FEATURE_DSP ) && (__ARM_FEATURE_DSP == 1 ))
267+ int32_t hi , lo ;
268+ int32_t bits = 16 ; // saturate to 16 bits
269+ int32_t shift = 0 ; // shift is done automatically
270+ asm volatile ("smulwb %0, %1, %2" : "=r" (lo ) : "r" (mul ), "r" (val ));
271+ asm volatile ("smulwt %0, %1, %2" : "=r" (hi ) : "r" (mul ), "r" (val ));
272+ asm volatile ("ssat %0, %1, %2, asr %3" : "=r" (lo ) : "I" (bits ), "r" (lo ), "I" (shift ));
273+ asm volatile ("ssat %0, %1, %2, asr %3" : "=r" (hi ) : "I" (bits ), "r" (hi ), "I" (shift ));
274+ asm volatile ("pkhbt %0, %1, %2, lsl #16" : "=r" (val ) : "r" (lo ), "r" (hi )); // pack
275+ return val ;
276+ #else
277+ uint32_t result = 0 ;
278+ //TODO:
279+ for (int8_t i = 0 ; i < 2 ; i ++ ) {
280+ int16_t ai = val >> (sizeof (int16_t ) * 8 * i );
281+ }
282+ return result ;
283+ #endif
284+ }
285+
218286audioio_get_buffer_result_t audioio_mixer_get_buffer (audioio_mixer_obj_t * self ,
219287 bool single_channel ,
220288 uint8_t channel ,
@@ -285,6 +353,22 @@ audioio_get_buffer_result_t audioio_mixer_get_buffer(audioio_mixer_obj_t* self,
285353 sample_value = voice -> remaining_buffer [j ];
286354 }
287355
356+ // apply the mixer gain
357+ if (!self -> samples_signed ) {
358+ if (self -> bits_per_sample == 8 ) {
359+ sample_value = mult8unsigned (sample_value , voice -> gain );
360+ } else {
361+ sample_value = mult16unsigned (sample_value , voice -> gain );
362+ }
363+ }
364+ else {
365+ if (self -> bits_per_sample == 8 ) {
366+ sample_value = mult8signed (sample_value , voice -> gain );
367+ } else {
368+ sample_value = mult16signed (sample_value , voice -> gain );
369+ }
370+ }
371+
288372 if (!voices_active ) {
289373 word_buffer [i ] = sample_value ;
290374 } else {
0 commit comments