55// Author: Bartosz Kokoszko <bartoszx.kokoszko@intel.com>
66// Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
77
8+ #include <sof/audio/format.h>
89#include <errno.h>
910#include <stddef.h>
1011#include <stdint.h>
@@ -262,7 +263,86 @@ void downmix32bit_5_0_mono(struct up_down_mixer_data *cd, const uint8_t * const
262263void downmix32bit_5_1 (struct up_down_mixer_data * cd , const uint8_t * const in_data ,
263264 const uint32_t in_size , uint8_t * const out_data )
264265{
265- sof_panic (0 );
266+ const uint8_t left_slot = get_channel_location (cd -> in_channel_map , CHANNEL_LEFT );
267+ const uint8_t center_slot = get_channel_location (cd -> in_channel_map , CHANNEL_CENTER );
268+ const uint8_t right_slot = get_channel_location (cd -> in_channel_map , CHANNEL_RIGHT );
269+ uint8_t left_surround_slot = get_channel_location (cd -> in_channel_map , CHANNEL_LEFT_SURROUND );
270+ uint8_t right_surround_slot = get_channel_location (cd -> in_channel_map , CHANNEL_RIGHT_SURROUND );
271+ const uint8_t lfe_slot = get_channel_location (cd -> in_channel_map , CHANNEL_LFE );
272+
273+ /* Must support also 5.1 Surround */
274+ const bool surround_5_1_channel_map = (left_surround_slot == CHANNEL_INVALID ) &&
275+ (right_surround_slot == CHANNEL_INVALID );
276+
277+ if (surround_5_1_channel_map ) {
278+ left_surround_slot = get_channel_location (cd -> in_channel_map , CHANNEL_LEFT_SIDE );
279+ right_surround_slot = get_channel_location (cd -> in_channel_map , CHANNEL_RIGHT_SIDE );
280+ }
281+
282+ /* Load the downmix coefficients. */
283+ int32_t P_coefficient_left = cd -> downmix_coefficients [CHANNEL_LEFT ];
284+ int32_t P_coefficient_center = cd -> downmix_coefficients [CHANNEL_CENTER ];
285+ int32_t P_coefficient_right = cd -> downmix_coefficients [CHANNEL_RIGHT ];
286+ int32_t P_coefficient_left_surround = cd -> downmix_coefficients [CHANNEL_LEFT_SURROUND ];
287+ int32_t P_coefficient_right_surround = cd -> downmix_coefficients [CHANNEL_RIGHT_SURROUND ];
288+ int32_t P_coefficient_lfe = cd -> downmix_coefficients [CHANNEL_LFE ];
289+
290+ if (surround_5_1_channel_map ) {
291+ P_coefficient_left_surround = cd -> downmix_coefficients [CHANNEL_LEFT_SIDE ];
292+ P_coefficient_right_surround = cd -> downmix_coefficients [CHANNEL_RIGHT_SIDE ];
293+ }
294+
295+ const int32_t * input_left = (int32_t * )(in_data + (left_slot << 2 ));
296+ const int32_t * input_center = (int32_t * )(in_data + (center_slot << 2 ));
297+ const int32_t * input_right = (int32_t * )(in_data + (right_slot << 2 ));
298+ const int32_t * input_left_surround = (int32_t * )(in_data + (left_surround_slot << 2 ));
299+ const int32_t * input_right_surround = (int32_t * )(in_data + (right_surround_slot << 2 ));
300+ const int32_t * input_lfe = (int32_t * )(in_data + (lfe_slot << 2 ));
301+
302+ /* Downmixer single store. */
303+ int32_t * output_left = (int32_t * )(out_data );
304+ int32_t * output_right = (int32_t * )(out_data + sizeof (int32_t ));
305+
306+ /*
307+ * We don't need to initialize those registers in loop's body.
308+ * Using non accumulating multiplication for the first left,rignt channels
309+ * is more efficient.
310+ * For non 5.1 version we cannot use this optimization, we don't know
311+ * which channel is present and which multiplication should reset output
312+ * accumulators.
313+ */
314+ int64_t Q_tmp_left ;
315+ int64_t Q_tmp_right ;
316+
317+ const int32_t * const end_input_left = input_left + (in_size / (sizeof (int32_t )));
318+
319+ while (input_left < end_input_left ) {
320+ /* Accumulate as Q1.31 * Q1.31 -> Q2.62 */
321+ Q_tmp_left = (int64_t )P_coefficient_center * * input_center ;
322+ input_center += 6 ;
323+
324+ Q_tmp_left += (int64_t )P_coefficient_lfe * * input_lfe ;
325+ input_lfe += 6 ;
326+ Q_tmp_right = Q_tmp_left ;
327+
328+ Q_tmp_left += (int64_t )P_coefficient_left * * input_left ;
329+ input_left += 6 ;
330+
331+ Q_tmp_right += (int64_t )P_coefficient_right * * input_right ;
332+ input_right += 6 ;
333+
334+ Q_tmp_left += (int64_t )P_coefficient_left_surround * * input_left_surround ;
335+ input_left_surround += 6 ;
336+
337+ Q_tmp_right += (int64_t )P_coefficient_right_surround * * input_right_surround ;
338+ input_right_surround += 6 ;
339+
340+ /* Shift with round to Q1.31 and saturate and store output */
341+ * output_left = sat_int32 (Q_SHIFT_RND (Q_tmp_left , 62 , 31 ));
342+ * output_right = sat_int32 (Q_SHIFT_RND (Q_tmp_right , 62 , 31 ));
343+ output_left += 2 ;
344+ output_right += 2 ;
345+ }
266346}
267347
268348void downmix32bit_7_1 (struct up_down_mixer_data * cd , const uint8_t * const in_data ,
@@ -274,7 +354,15 @@ void downmix32bit_7_1(struct up_down_mixer_data *cd, const uint8_t * const in_da
274354void downmix16bit_stereo (struct up_down_mixer_data * cd , const uint8_t * const in_data ,
275355 const uint32_t in_size , uint8_t * const out_data )
276356{
277- sof_panic (0 );
357+ int32_t sum ;
358+ const int16_t * in_data16 = (int16_t * )in_data ;
359+ int16_t * out_data16 = (int16_t * )out_data ;
360+ int idx ;
361+
362+ for (idx = 0 ; idx < (in_size >> 2 ); ++ idx ) {
363+ sum = (int32_t )in_data16 [2 * idx ] + in_data16 [2 * idx + 1 ];
364+ out_data16 [idx ] = sat_int16 ((sum + 1 ) >> 1 );
365+ }
278366}
279367
280368void shiftcopy16bit_mono (struct up_down_mixer_data * cd , const uint8_t * const in_data ,
@@ -326,7 +414,15 @@ void downmix16bit_4ch_mono(struct up_down_mixer_data *cd, const uint8_t * const
326414void downmix32bit_stereo (struct up_down_mixer_data * cd , const uint8_t * const in_data ,
327415 const uint32_t in_size , uint8_t * const out_data )
328416{
329- sof_panic (0 );
417+ int64_t sum ;
418+ int32_t * in_data32 = (int32_t * )in_data ;
419+ int32_t * out_data32 = (int32_t * )out_data ;
420+ int idx ;
421+
422+ for (idx = 0 ; idx < (in_size >> 3 ); idx ++ ) {
423+ sum = (int64_t )in_data32 [2 * idx ] + in_data32 [2 * idx + 1 ];
424+ out_data32 [idx ] = sat_int32 ((sum + 1 ) >> 1 );
425+ }
330426}
331427
332428void downmix32bit_3_1_mono (struct up_down_mixer_data * cd , const uint8_t * const in_data ,
0 commit comments