From 44eb648b28f366e7c962a587d049910e5a374a8d Mon Sep 17 00:00:00 2001 From: Thomas Dettbarn Date: Fri, 29 Aug 2025 10:26:29 +0200 Subject: [PATCH 01/10] added a fix-point version of the ambisonics converter. --- lib_util/ambi_convert.c | 448 ++++++++++++++++++++++++++++++++++++++++ lib_util/ambi_convert.h | 95 +++++++++ 2 files changed, 543 insertions(+) create mode 100644 lib_util/ambi_convert.c create mode 100644 lib_util/ambi_convert.h diff --git a/lib_util/ambi_convert.c b/lib_util/ambi_convert.c new file mode 100644 index 000000000..05814651f --- /dev/null +++ b/lib_util/ambi_convert.c @@ -0,0 +1,448 @@ +/****************************************************************************************************** + + (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#include +#include +#include "ambi_convert.h" + +#define THISQ Q29 + +#define ONE_1_Q29 536870912l /* 1.0f */ + +#define SQRT_2_Q29 759250112l /* sqrtf(2.0f) */ +#define SQRT_3_Q29 929887680l /* sqrtf(3.0f) */ +#define SQRT_5_Q29 1200479872l /* sqrtf(5.0f) */ +#define SQRT_7_Q29 1420426880l /* sqrtf(7.0f) */ + +#define INV_SQRT_2_Q29 379625024l /* 1.0f/sqrtf(2.0f) */ +#define INV_SQRT_3_Q29 309962528l /* 1.0f/sqrtf(3.0f) */ +#define INV_SQRT_5_Q29 240095920l /* 1.0f/sqrtf(5.0f) */ +#define INV_SQRT_7_Q29 202918096l /* 1.0f/sqrtf(7.0f) */ + +#define TWO_OVER_SQRT_3_Q29 619925120l /* 2.0f/sqrtf(3.0f) */ +#define THREE_OVER_SQRT_5_Q29 720287936l /* 3.0f/sqrtf(5.0f) */ +#define SQRT_8_OVER_5_Q29 679093952l /* sqrtf(8.0f/5.0f) */ +#define SQRT_45_OVER_32_Q29 636650560l /* sqrtf(45.0f/32.0f) */ + +#define INV_TWO_OVER_SQRT_3_Q29 464943840l /* 1.0f/TWO_OVER_SQRT_3_Q29 */ +#define INV_THREE_OVER_SQRT_5_Q29 400159968l /* 1.0f/THREE_OVER_SQRT_5_Q29 */ +#define INV_SQRT_8_OVER_5_Q29 424433728l /* 1.0f/INV_SQRT_8_OVER_5_Q29 */ +#define INV_SQRT_45_OVER_32_Q29 452729280l /* 1.0f/SQRT_45_OVER_32_Q29 */ + + + + +/* -------------------------------- + normalization conversion tables + -------------------------------- */ + +static const Word32 SN3D_N3D[AMBI_MAX_CHANNELS] = { ONE_1_Q29, + SQRT_3_Q29, SQRT_3_Q29, SQRT_3_Q29, + SQRT_5_Q29, SQRT_5_Q29, SQRT_5_Q29, SQRT_5_Q29, SQRT_5_Q29, + SQRT_7_Q29, SQRT_7_Q29, SQRT_7_Q29, SQRT_7_Q29, SQRT_7_Q29, SQRT_7_Q29, SQRT_7_Q29 }; + +static const Word32 N3D_SN3D[AMBI_MAX_CHANNELS] = { ONE_1_Q29, + INV_SQRT_3_Q29, INV_SQRT_3_Q29, INV_SQRT_3_Q29, + INV_SQRT_5_Q29, INV_SQRT_5_Q29, INV_SQRT_5_Q29, INV_SQRT_5_Q29, INV_SQRT_5_Q29, + INV_SQRT_7_Q29, INV_SQRT_7_Q29, INV_SQRT_7_Q29, INV_SQRT_7_Q29, INV_SQRT_7_Q29, INV_SQRT_7_Q29, INV_SQRT_7_Q29 }; + + +static const Word32 SN3D_MAXN[AMBI_MAX_CHANNELS] = { ONE_1_Q29, + ONE_1_Q29, ONE_1_Q29, ONE_1_Q29, + TWO_OVER_SQRT_3_Q29, TWO_OVER_SQRT_3_Q29, ONE_1_Q29, TWO_OVER_SQRT_3_Q29, TWO_OVER_SQRT_3_Q29, + SQRT_8_OVER_5_Q29, THREE_OVER_SQRT_5_Q29, SQRT_45_OVER_32_Q29, ONE_1_Q29, SQRT_45_OVER_32_Q29, THREE_OVER_SQRT_5_Q29, SQRT_8_OVER_5_Q29 }; + +static const Word32 MAXN_SN3D[AMBI_MAX_CHANNELS] = { ONE_1_Q29, + ONE_1_Q29, ONE_1_Q29, ONE_1_Q29, + INV_TWO_OVER_SQRT_3_Q29, INV_TWO_OVER_SQRT_3_Q29, ONE_1_Q29, INV_TWO_OVER_SQRT_3_Q29, INV_TWO_OVER_SQRT_3_Q29, + INV_SQRT_8_OVER_5_Q29, INV_THREE_OVER_SQRT_5_Q29, INV_SQRT_45_OVER_32_Q29, ONE_1_Q29, INV_SQRT_45_OVER_32_Q29, INV_THREE_OVER_SQRT_5_Q29, INV_SQRT_8_OVER_5_Q29 }; + +static const Word32 SN3D_FM[AMBI_MAX_CHANNELS] = { INV_SQRT_2_Q29, + ONE_1_Q29,ONE_1_Q29,ONE_1_Q29, + TWO_OVER_SQRT_3_Q29, TWO_OVER_SQRT_3_Q29, ONE_1_Q29, TWO_OVER_SQRT_3_Q29, TWO_OVER_SQRT_3_Q29, + SQRT_8_OVER_5_Q29, THREE_OVER_SQRT_5_Q29, SQRT_45_OVER_32_Q29, ONE_1_Q29, SQRT_45_OVER_32_Q29, THREE_OVER_SQRT_5_Q29, SQRT_8_OVER_5_Q29 }; + +static const Word32 FM_SN3D[AMBI_MAX_CHANNELS] = { SQRT_2_Q29, + ONE_1_Q29, ONE_1_Q29, ONE_1_Q29, + INV_TWO_OVER_SQRT_3_Q29, INV_TWO_OVER_SQRT_3_Q29, ONE_1_Q29, INV_TWO_OVER_SQRT_3_Q29, INV_TWO_OVER_SQRT_3_Q29, + INV_SQRT_8_OVER_5_Q29, INV_THREE_OVER_SQRT_5_Q29, INV_SQRT_45_OVER_32_Q29, ONE_1_Q29, INV_SQRT_45_OVER_32_Q29, INV_THREE_OVER_SQRT_5_Q29, INV_SQRT_8_OVER_5_Q29 }; + +/* ---------------------------- + channel re-ordering tables + ---------------------------- */ + +static const int16_t REORDER_FM_ACN[AMBI_MAX_CHANNELS] = { 0, + 2, 3, 1, + 8, 6, 4, 5, 7, + 15, 13, 11, 9, 10, 12, 14 }; + +static const int16_t REORDER_SID_ACN[AMBI_MAX_CHANNELS] = { 0, + 2, 3, 1, + 5, 7, 8, 6, 4, + 10, 12, 14, 15, 13, 11, 9 }; + +static const int16_t REORDER_ACN_FM[AMBI_MAX_CHANNELS] = { 0, + 3, 1, 2, + 6, 7, 5, 8, 4, + 12, 13, 11, 14, 10, 15, 9 }; + +static const int16_t REORDER_ACN_SID[AMBI_MAX_CHANNELS] = { 0, + 3, 1, 2, + 8, 4, 7, 5, 6, + 15, 9, 14, 10, 13, 11, 12 }; + +/* ---------------------------------- + API functions for the conversion + ---------------------------------- */ + +/*-------------------------------------------------------------------------* +* convert_ambi_format() +* +* Convert signal between ACN-SN3D and other common ambisonics conventions +--------------------------------------------------------------------------*/ + +AMBI_CONVERT_ERROR convert_ambi_format( + Word32 *in[], /* i: input ambisonics channels */ + Word32 *out[], /* o: output ambisonics channels */ + int16_t order, /* i: ambisonics order */ + AMBI_FMT in_format, /* i: input ambisonics format */ + AMBI_FMT out_format /* i: output ambisonics format */ +) +{ + + Word32 tmp[AMBI_MAX_CHANNELS * L_FRAME48k]; + Word32 *p_tmp[AMBI_MAX_CHANNELS]; + AMBI_CONVERT_ERROR err = AMBI_CONVERT_OK; + + AMBI_CHANNEL_ORDER ch_ord_in = AMBI_CHANNEL_ORDER_ACN; + AMBI_CHANNEL_ORDER ch_ord_out = AMBI_CHANNEL_ORDER_ACN; + + AMBI_CHANNEL_NORM ch_norm_in = AMBI_NORM_SN3D; + AMBI_CHANNEL_NORM ch_norm_out = AMBI_NORM_SN3D; + + assert( order <= 3 ); + + if ( in_format != AMBI_FMT_ACN_SN3D && out_format != AMBI_FMT_ACN_SN3D ) + { + assert( 0 && "Conversion only supported to and from ACN-SN3D" ); + } + + for ( int16_t j = 0; j < AMBI_MAX_CHANNELS; j++ ) + { + p_tmp[j] = &tmp[j * L_FRAME48k]; + } + + switch ( in_format ) + { + case AMBI_FMT_ACN_SN3D: + ch_ord_in = AMBI_CHANNEL_ORDER_ACN; + ch_norm_in = AMBI_NORM_SN3D; + break; + case AMBI_FMT_ACN_N3D: + ch_ord_in = AMBI_CHANNEL_ORDER_ACN; + ch_norm_in = AMBI_NORM_N3D; + break; + case AMBI_FMT_FM_MAXN: + ch_ord_in = AMBI_CHANNEL_ORDER_FM; + ch_norm_in = AMBI_NORM_MAXN; + break; + case AMBI_FMT_FM_FM: + ch_ord_in = AMBI_CHANNEL_ORDER_FM; + ch_norm_in = AMBI_NORM_FM; + break; + case AMBI_FMT_SID_SN3D: + ch_ord_in = AMBI_CHANNEL_ORDER_SID; + ch_norm_in = AMBI_NORM_SN3D; + break; + case AMBI_FMT_SID_N3D: + ch_ord_in = AMBI_CHANNEL_ORDER_SID; + ch_norm_in = AMBI_NORM_N3D; + break; + default: + return AMBI_CONVERT_UNSUPPORTED_CONVERSION; + } + + switch ( out_format ) + { + case AMBI_FMT_ACN_SN3D: + ch_ord_out = AMBI_CHANNEL_ORDER_ACN; + ch_norm_out = AMBI_NORM_SN3D; + break; + case AMBI_FMT_ACN_N3D: + ch_ord_out = AMBI_CHANNEL_ORDER_ACN; + ch_norm_out = AMBI_NORM_N3D; + break; + case AMBI_FMT_FM_MAXN: + ch_ord_out = AMBI_CHANNEL_ORDER_FM; + ch_norm_out = AMBI_NORM_MAXN; + break; + case AMBI_FMT_FM_FM: + ch_ord_out = AMBI_CHANNEL_ORDER_FM; + ch_norm_out = AMBI_NORM_FM; + break; + case AMBI_FMT_SID_SN3D: + ch_ord_out = AMBI_CHANNEL_ORDER_SID; + ch_norm_out = AMBI_NORM_SN3D; + break; + case AMBI_FMT_SID_N3D: + ch_ord_out = AMBI_CHANNEL_ORDER_SID; + ch_norm_out = AMBI_NORM_N3D; + break; + default: + return AMBI_CONVERT_UNSUPPORTED_CONVERSION; + } + + if ( in_format == AMBI_FMT_ACN_SN3D && ch_norm_in != ch_norm_out ) + { + if ( ch_ord_in != ch_ord_out ) + { + if ( ( err = renormalize_channels( in, p_tmp, order, ch_norm_in, ch_norm_out ) ) != AMBI_CONVERT_OK ) + { + return err; + } + if ( ( err = reorder_channels( p_tmp, out, order, ch_ord_in, ch_ord_out ) ) != AMBI_CONVERT_OK ) + { + return err; + } + } + else + { + if ( ( err = renormalize_channels( in, out, order, ch_norm_in, ch_norm_out ) ) != AMBI_CONVERT_OK ) + { + return err; + } + } + } + else if ( in_format == AMBI_FMT_ACN_SN3D && ch_ord_in != ch_ord_out ) + { + if ( ( err = reorder_channels( in, out, order, ch_ord_in, ch_ord_out ) ) != AMBI_CONVERT_OK ) + { + return err; + } + } + else if ( out_format == AMBI_FMT_ACN_SN3D && ch_norm_in != ch_norm_out ) + { + if ( ch_ord_in != ch_ord_out ) + { + if ( ( err = reorder_channels( in, p_tmp, order, ch_ord_in, ch_ord_out ) ) != AMBI_CONVERT_OK ) + { + return err; + } + if ( ( err = renormalize_channels( p_tmp, out, order, ch_norm_in, ch_norm_out ) ) != AMBI_CONVERT_OK ) + { + return err; + } + } + else + { + if ( ( err = renormalize_channels( in, out, order, ch_norm_in, ch_norm_out ) ) != AMBI_CONVERT_OK ) + { + return err; + } + } + } + else if ( out_format == AMBI_FMT_ACN_SN3D && ch_ord_in != ch_ord_out ) + { + if ( ( err = reorder_channels( in, out, order, ch_ord_in, ch_ord_out ) ) != AMBI_CONVERT_OK ) + { + return err; + } + } + else if ( out_format == AMBI_FMT_ACN_SN3D && in_format == AMBI_FMT_ACN_SN3D ) + { + int16_t i_chan = 0; + int16_t n_chan = i_mult2( add( order, 1), add( order, 1) ); + + for ( i_chan = 0; i_chan < n_chan; i_chan++ ) + { + int16_t i = 0; + for ( i = 0; i < L_FRAME48k; i++ ) + { + out[i_chan][i] = in[i_chan][i]; + } + } + } + else + { + assert( 0 && "This should never happen!" ); + } + + return AMBI_CONVERT_OK; +} + +/*-------------------------------------------------------------------------* +* renormalize_channels() +* +* Rescale audio channels according to the selected ambisonics convention +--------------------------------------------------------------------------*/ + +AMBI_CONVERT_ERROR renormalize_channels( + Word32 *in[], /* i: input ambisonics channels */ + Word32 *out[], /* o: output ambisonics channels */ + int16_t order, /* i: ambisonics order */ + AMBI_CHANNEL_NORM in_format, /* i: input ambisonics format */ + AMBI_CHANNEL_NORM out_format /* i: output ambisonics format */ +) +{ + int16_t n_chan = i_mult2( add( order, 1), add( order, 1) ); + int16_t i_chan, i; + const Word32 *conversion_table = 0; + + /* conversion factors are applied on the channels assuming that they are still/already in ACN order */ + if ( in_format == AMBI_NORM_SN3D ) + { + if ( out_format == AMBI_NORM_N3D ) + { + conversion_table = SN3D_N3D; + } + else if ( out_format == AMBI_NORM_MAXN ) + { + conversion_table = SN3D_MAXN; + } + else if ( out_format == AMBI_NORM_FM ) + { + conversion_table = SN3D_FM; + } + else + { + return AMBI_CONVERT_UNSUPPORTED_CONVERSION; + } + } + else if ( out_format == AMBI_NORM_SN3D ) + { + if ( in_format == AMBI_NORM_N3D ) + { + conversion_table = N3D_SN3D; + } + else if ( in_format == AMBI_NORM_MAXN ) + { + conversion_table = MAXN_SN3D; + } + else if ( in_format == AMBI_NORM_FM ) + { + conversion_table = FM_SN3D; + } + else + { + return AMBI_CONVERT_UNSUPPORTED_CONVERSION; + } + } + else + { + return AMBI_CONVERT_UNSUPPORTED_CONVERSION; + } + + + for ( i_chan = 0; i_chan < n_chan; i_chan++ ) + { + Word32 conversion_factor = conversion_table[i_chan]; + for ( i = 0; i < L_FRAME48k; i++ ) + { + Word64 tmp; + tmp= W_mult0_32x32(in[i_chan][i], conversion_factor ); + tmp= W_shr(tmp, Q29 ); + out[i_chan][i] = W_extract_h( tmp ); + } + } + + return AMBI_CONVERT_OK; +} + +/*-------------------------------------------------------------------------* +* reorder_channels() +* +* Reorder channels according to the selected ambisonics convention +--------------------------------------------------------------------------*/ + +AMBI_CONVERT_ERROR reorder_channels( + Word32 *in[], /* i: input ambisonics channels */ + Word32 *out[], /* o: output ambisonics channels */ + int16_t order, /* i: ambisonics order */ + AMBI_CHANNEL_ORDER in_format, /* i: input ambisonics format */ + AMBI_CHANNEL_ORDER out_format /* i: output ambisonics format */ +) +{ + int16_t n_chan = i_mult2( add( order, 1), add( order, 1) ); + int16_t i_chan, i; + Word32 tmp[AMBI_MAX_CHANNELS]; + const int16_t *idx_table = 0; + + if ( in_format == AMBI_CHANNEL_ORDER_ACN ) + { + if ( out_format == AMBI_CHANNEL_ORDER_FM ) + { + idx_table = REORDER_ACN_FM; + } + else if ( out_format == AMBI_CHANNEL_ORDER_SID ) + { + idx_table = REORDER_ACN_SID; + } + else + { + return AMBI_CONVERT_UNSUPPORTED_CONVERSION; + } + } + else if ( out_format == AMBI_CHANNEL_ORDER_ACN ) + { + if ( in_format == AMBI_CHANNEL_ORDER_FM ) + { + idx_table = REORDER_FM_ACN; + } + else if ( in_format == AMBI_CHANNEL_ORDER_SID ) + { + idx_table = REORDER_SID_ACN; + } + else + { + return AMBI_CONVERT_UNSUPPORTED_CONVERSION; + } + } + else + { + return AMBI_CONVERT_UNSUPPORTED_CONVERSION; + } + + for ( i = 0; i < L_FRAME48k; i++ ) + { + for ( i_chan = 0; i_chan < n_chan; i_chan++ ) + { + int16_t idx = idx_table[i_chan]; + tmp[i_chan] = in[idx][i]; + } + for ( i_chan = 0; i_chan < n_chan; i_chan++ ) + { + out[i_chan][i] = tmp[i_chan]; + } + } + + return AMBI_CONVERT_OK; +} diff --git a/lib_util/ambi_convert.h b/lib_util/ambi_convert.h new file mode 100644 index 000000000..d658c9a75 --- /dev/null +++ b/lib_util/ambi_convert.h @@ -0,0 +1,95 @@ +/****************************************************************************************************** + + (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#ifndef AMBI_CONVERT_H +#define AMBI_CONVERT_H + +#include + +#define L_FRAME48k 960 +#define AMBI_MAX_CHANNELS 16 + +typedef enum +{ + AMBI_FMT_ACN_SN3D = 0, + AMBI_FMT_ACN_N3D, + AMBI_FMT_FM_MAXN, + AMBI_FMT_FM_FM, + AMBI_FMT_SID_SN3D, + AMBI_FMT_SID_N3D +} AMBI_FMT; + +typedef enum +{ + AMBI_NORM_SN3D = 0, + AMBI_NORM_N3D, + AMBI_NORM_MAXN, + AMBI_NORM_FM +} AMBI_CHANNEL_NORM; + +typedef enum +{ + AMBI_CHANNEL_ORDER_ACN = 0, + AMBI_CHANNEL_ORDER_FM, + AMBI_CHANNEL_ORDER_SID +} AMBI_CHANNEL_ORDER; + +typedef enum +{ + AMBI_CONVERT_OK = 0, + AMBI_CONVERT_UNSUPPORTED_CONVERSION +} AMBI_CONVERT_ERROR; + +AMBI_CONVERT_ERROR convert_ambi_format( + Word32 *in[], /* i: input ambisonics channels */ + Word32 *out[], /* o: output ambisonics channels */ + int16_t order, /* i: ambisonics order */ + AMBI_FMT in_format, /* i: input ambisonics format */ + AMBI_FMT out_format /* i: output ambisonics format */ +); + +AMBI_CONVERT_ERROR renormalize_channels( + Word32 *in[], /* i: input ambisonics channels */ + Word32 *out[], /* o: output ambisonics channels */ + int16_t order, /* i: ambisonics order */ + AMBI_CHANNEL_NORM in_format, /* i: input ambisonics format */ + AMBI_CHANNEL_NORM out_format /* i: output ambisonics format */ +); + +AMBI_CONVERT_ERROR reorder_channels( + Word32 *in[], /* i: input ambisonics channels */ + Word32 *out[], /* o: output ambisonics channels */ + int16_t order, /* i: ambisonics order */ + AMBI_CHANNEL_ORDER in_format, /* i: input ambisonics format */ + AMBI_CHANNEL_ORDER out_format /* i: output ambisonics format */ +); +#endif -- GitLab From c43527100d3844a38ee082fff6ec94fca300fb6e Mon Sep 17 00:00:00 2001 From: Thomas Dettbarn Date: Fri, 29 Aug 2025 10:55:39 +0200 Subject: [PATCH 02/10] compiles. --- lib_util/ambi_convert.c | 84 ++++++++++++++++++++--------------------- lib_util/ambi_convert.h | 7 ++++ 2 files changed, 48 insertions(+), 43 deletions(-) diff --git a/lib_util/ambi_convert.c b/lib_util/ambi_convert.c index 05814651f..90fa692a4 100644 --- a/lib_util/ambi_convert.c +++ b/lib_util/ambi_convert.c @@ -34,31 +34,29 @@ #include #include "ambi_convert.h" -#define THISQ Q29 +#define THISQ Q29 -#define ONE_1_Q29 536870912l /* 1.0f */ +#define ONE_1_Q29 536870912l /* 1.0f */ -#define SQRT_2_Q29 759250112l /* sqrtf(2.0f) */ -#define SQRT_3_Q29 929887680l /* sqrtf(3.0f) */ -#define SQRT_5_Q29 1200479872l /* sqrtf(5.0f) */ -#define SQRT_7_Q29 1420426880l /* sqrtf(7.0f) */ +#define SQRT_2_Q29 759250112l /* sqrtf(2.0f) */ +#define SQRT_3_Q29 929887680l /* sqrtf(3.0f) */ +#define SQRT_5_Q29 1200479872l /* sqrtf(5.0f) */ +#define SQRT_7_Q29 1420426880l /* sqrtf(7.0f) */ -#define INV_SQRT_2_Q29 379625024l /* 1.0f/sqrtf(2.0f) */ -#define INV_SQRT_3_Q29 309962528l /* 1.0f/sqrtf(3.0f) */ -#define INV_SQRT_5_Q29 240095920l /* 1.0f/sqrtf(5.0f) */ -#define INV_SQRT_7_Q29 202918096l /* 1.0f/sqrtf(7.0f) */ - -#define TWO_OVER_SQRT_3_Q29 619925120l /* 2.0f/sqrtf(3.0f) */ -#define THREE_OVER_SQRT_5_Q29 720287936l /* 3.0f/sqrtf(5.0f) */ -#define SQRT_8_OVER_5_Q29 679093952l /* sqrtf(8.0f/5.0f) */ -#define SQRT_45_OVER_32_Q29 636650560l /* sqrtf(45.0f/32.0f) */ - -#define INV_TWO_OVER_SQRT_3_Q29 464943840l /* 1.0f/TWO_OVER_SQRT_3_Q29 */ -#define INV_THREE_OVER_SQRT_5_Q29 400159968l /* 1.0f/THREE_OVER_SQRT_5_Q29 */ -#define INV_SQRT_8_OVER_5_Q29 424433728l /* 1.0f/INV_SQRT_8_OVER_5_Q29 */ -#define INV_SQRT_45_OVER_32_Q29 452729280l /* 1.0f/SQRT_45_OVER_32_Q29 */ +#define INV_SQRT_2_Q29 379625024l /* 1.0f/sqrtf(2.0f) */ +#define INV_SQRT_3_Q29 309962528l /* 1.0f/sqrtf(3.0f) */ +#define INV_SQRT_5_Q29 240095920l /* 1.0f/sqrtf(5.0f) */ +#define INV_SQRT_7_Q29 202918096l /* 1.0f/sqrtf(7.0f) */ +#define TWO_OVER_SQRT_3_Q29 619925120l /* 2.0f/sqrtf(3.0f) */ +#define THREE_OVER_SQRT_5_Q29 720287936l /* 3.0f/sqrtf(5.0f) */ +#define SQRT_8_OVER_5_Q29 679093952l /* sqrtf(8.0f/5.0f) */ +#define SQRT_45_OVER_32_Q29 636650560l /* sqrtf(45.0f/32.0f) */ +#define INV_TWO_OVER_SQRT_3_Q29 464943840l /* 1.0f/TWO_OVER_SQRT_3_Q29 */ +#define INV_THREE_OVER_SQRT_5_Q29 400159968l /* 1.0f/THREE_OVER_SQRT_5_Q29 */ +#define INV_SQRT_8_OVER_5_Q29 424433728l /* 1.0f/INV_SQRT_8_OVER_5_Q29 */ +#define INV_SQRT_45_OVER_32_Q29 452729280l /* 1.0f/SQRT_45_OVER_32_Q29 */ /* -------------------------------- @@ -66,35 +64,35 @@ -------------------------------- */ static const Word32 SN3D_N3D[AMBI_MAX_CHANNELS] = { ONE_1_Q29, - SQRT_3_Q29, SQRT_3_Q29, SQRT_3_Q29, - SQRT_5_Q29, SQRT_5_Q29, SQRT_5_Q29, SQRT_5_Q29, SQRT_5_Q29, - SQRT_7_Q29, SQRT_7_Q29, SQRT_7_Q29, SQRT_7_Q29, SQRT_7_Q29, SQRT_7_Q29, SQRT_7_Q29 }; + SQRT_3_Q29, SQRT_3_Q29, SQRT_3_Q29, + SQRT_5_Q29, SQRT_5_Q29, SQRT_5_Q29, SQRT_5_Q29, SQRT_5_Q29, + SQRT_7_Q29, SQRT_7_Q29, SQRT_7_Q29, SQRT_7_Q29, SQRT_7_Q29, SQRT_7_Q29, SQRT_7_Q29 }; static const Word32 N3D_SN3D[AMBI_MAX_CHANNELS] = { ONE_1_Q29, - INV_SQRT_3_Q29, INV_SQRT_3_Q29, INV_SQRT_3_Q29, - INV_SQRT_5_Q29, INV_SQRT_5_Q29, INV_SQRT_5_Q29, INV_SQRT_5_Q29, INV_SQRT_5_Q29, - INV_SQRT_7_Q29, INV_SQRT_7_Q29, INV_SQRT_7_Q29, INV_SQRT_7_Q29, INV_SQRT_7_Q29, INV_SQRT_7_Q29, INV_SQRT_7_Q29 }; + INV_SQRT_3_Q29, INV_SQRT_3_Q29, INV_SQRT_3_Q29, + INV_SQRT_5_Q29, INV_SQRT_5_Q29, INV_SQRT_5_Q29, INV_SQRT_5_Q29, INV_SQRT_5_Q29, + INV_SQRT_7_Q29, INV_SQRT_7_Q29, INV_SQRT_7_Q29, INV_SQRT_7_Q29, INV_SQRT_7_Q29, INV_SQRT_7_Q29, INV_SQRT_7_Q29 }; static const Word32 SN3D_MAXN[AMBI_MAX_CHANNELS] = { ONE_1_Q29, - ONE_1_Q29, ONE_1_Q29, ONE_1_Q29, - TWO_OVER_SQRT_3_Q29, TWO_OVER_SQRT_3_Q29, ONE_1_Q29, TWO_OVER_SQRT_3_Q29, TWO_OVER_SQRT_3_Q29, - SQRT_8_OVER_5_Q29, THREE_OVER_SQRT_5_Q29, SQRT_45_OVER_32_Q29, ONE_1_Q29, SQRT_45_OVER_32_Q29, THREE_OVER_SQRT_5_Q29, SQRT_8_OVER_5_Q29 }; + ONE_1_Q29, ONE_1_Q29, ONE_1_Q29, + TWO_OVER_SQRT_3_Q29, TWO_OVER_SQRT_3_Q29, ONE_1_Q29, TWO_OVER_SQRT_3_Q29, TWO_OVER_SQRT_3_Q29, + SQRT_8_OVER_5_Q29, THREE_OVER_SQRT_5_Q29, SQRT_45_OVER_32_Q29, ONE_1_Q29, SQRT_45_OVER_32_Q29, THREE_OVER_SQRT_5_Q29, SQRT_8_OVER_5_Q29 }; static const Word32 MAXN_SN3D[AMBI_MAX_CHANNELS] = { ONE_1_Q29, - ONE_1_Q29, ONE_1_Q29, ONE_1_Q29, - INV_TWO_OVER_SQRT_3_Q29, INV_TWO_OVER_SQRT_3_Q29, ONE_1_Q29, INV_TWO_OVER_SQRT_3_Q29, INV_TWO_OVER_SQRT_3_Q29, - INV_SQRT_8_OVER_5_Q29, INV_THREE_OVER_SQRT_5_Q29, INV_SQRT_45_OVER_32_Q29, ONE_1_Q29, INV_SQRT_45_OVER_32_Q29, INV_THREE_OVER_SQRT_5_Q29, INV_SQRT_8_OVER_5_Q29 }; + ONE_1_Q29, ONE_1_Q29, ONE_1_Q29, + INV_TWO_OVER_SQRT_3_Q29, INV_TWO_OVER_SQRT_3_Q29, ONE_1_Q29, INV_TWO_OVER_SQRT_3_Q29, INV_TWO_OVER_SQRT_3_Q29, + INV_SQRT_8_OVER_5_Q29, INV_THREE_OVER_SQRT_5_Q29, INV_SQRT_45_OVER_32_Q29, ONE_1_Q29, INV_SQRT_45_OVER_32_Q29, INV_THREE_OVER_SQRT_5_Q29, INV_SQRT_8_OVER_5_Q29 }; static const Word32 SN3D_FM[AMBI_MAX_CHANNELS] = { INV_SQRT_2_Q29, - ONE_1_Q29,ONE_1_Q29,ONE_1_Q29, - TWO_OVER_SQRT_3_Q29, TWO_OVER_SQRT_3_Q29, ONE_1_Q29, TWO_OVER_SQRT_3_Q29, TWO_OVER_SQRT_3_Q29, - SQRT_8_OVER_5_Q29, THREE_OVER_SQRT_5_Q29, SQRT_45_OVER_32_Q29, ONE_1_Q29, SQRT_45_OVER_32_Q29, THREE_OVER_SQRT_5_Q29, SQRT_8_OVER_5_Q29 }; + ONE_1_Q29, ONE_1_Q29, ONE_1_Q29, + TWO_OVER_SQRT_3_Q29, TWO_OVER_SQRT_3_Q29, ONE_1_Q29, TWO_OVER_SQRT_3_Q29, TWO_OVER_SQRT_3_Q29, + SQRT_8_OVER_5_Q29, THREE_OVER_SQRT_5_Q29, SQRT_45_OVER_32_Q29, ONE_1_Q29, SQRT_45_OVER_32_Q29, THREE_OVER_SQRT_5_Q29, SQRT_8_OVER_5_Q29 }; static const Word32 FM_SN3D[AMBI_MAX_CHANNELS] = { SQRT_2_Q29, - ONE_1_Q29, ONE_1_Q29, ONE_1_Q29, - INV_TWO_OVER_SQRT_3_Q29, INV_TWO_OVER_SQRT_3_Q29, ONE_1_Q29, INV_TWO_OVER_SQRT_3_Q29, INV_TWO_OVER_SQRT_3_Q29, - INV_SQRT_8_OVER_5_Q29, INV_THREE_OVER_SQRT_5_Q29, INV_SQRT_45_OVER_32_Q29, ONE_1_Q29, INV_SQRT_45_OVER_32_Q29, INV_THREE_OVER_SQRT_5_Q29, INV_SQRT_8_OVER_5_Q29 }; + ONE_1_Q29, ONE_1_Q29, ONE_1_Q29, + INV_TWO_OVER_SQRT_3_Q29, INV_TWO_OVER_SQRT_3_Q29, ONE_1_Q29, INV_TWO_OVER_SQRT_3_Q29, INV_TWO_OVER_SQRT_3_Q29, + INV_SQRT_8_OVER_5_Q29, INV_THREE_OVER_SQRT_5_Q29, INV_SQRT_45_OVER_32_Q29, ONE_1_Q29, INV_SQRT_45_OVER_32_Q29, INV_THREE_OVER_SQRT_5_Q29, INV_SQRT_8_OVER_5_Q29 }; /* ---------------------------- channel re-ordering tables @@ -280,7 +278,7 @@ AMBI_CONVERT_ERROR convert_ambi_format( else if ( out_format == AMBI_FMT_ACN_SN3D && in_format == AMBI_FMT_ACN_SN3D ) { int16_t i_chan = 0; - int16_t n_chan = i_mult2( add( order, 1), add( order, 1) ); + int16_t n_chan = i_mult2( add( order, 1 ), add( order, 1 ) ); for ( i_chan = 0; i_chan < n_chan; i_chan++ ) { @@ -313,7 +311,7 @@ AMBI_CONVERT_ERROR renormalize_channels( AMBI_CHANNEL_NORM out_format /* i: output ambisonics format */ ) { - int16_t n_chan = i_mult2( add( order, 1), add( order, 1) ); + int16_t n_chan = i_mult2( add( order, 1 ), add( order, 1 ) ); int16_t i_chan, i; const Word32 *conversion_table = 0; @@ -368,8 +366,8 @@ AMBI_CONVERT_ERROR renormalize_channels( for ( i = 0; i < L_FRAME48k; i++ ) { Word64 tmp; - tmp= W_mult0_32x32(in[i_chan][i], conversion_factor ); - tmp= W_shr(tmp, Q29 ); + tmp = W_mult0_32_32( in[i_chan][i], conversion_factor ); + tmp = W_shr( tmp, Q29 ); out[i_chan][i] = W_extract_h( tmp ); } } @@ -391,7 +389,7 @@ AMBI_CONVERT_ERROR reorder_channels( AMBI_CHANNEL_ORDER out_format /* i: output ambisonics format */ ) { - int16_t n_chan = i_mult2( add( order, 1), add( order, 1) ); + int16_t n_chan = i_mult2( add( order, 1 ), add( order, 1 ) ); int16_t i_chan, i; Word32 tmp[AMBI_MAX_CHANNELS]; const int16_t *idx_table = 0; diff --git a/lib_util/ambi_convert.h b/lib_util/ambi_convert.h index d658c9a75..2b1f4480a 100644 --- a/lib_util/ambi_convert.h +++ b/lib_util/ambi_convert.h @@ -34,6 +34,13 @@ #define AMBI_CONVERT_H #include +#include "options.h" +#include "prot_fx.h" +#include "ivas_cnst.h" +#include +#include "wmc_auto.h" +#include "ivas_prot_fx.h" + #define L_FRAME48k 960 #define AMBI_MAX_CHANNELS 16 -- GitLab From 2233467aaee4d7e0a98caa6c33ac311da0a7a71f Mon Sep 17 00:00:00 2001 From: Thomas Dettbarn Date: Mon, 1 Sep 2025 12:31:31 +0200 Subject: [PATCH 03/10] typo in renormalize_channels() of ambi_convert.c caused wrong output. --- lib_util/ambi_convert.c | 2 +- scripts/compile_ambi_converter.sh | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 scripts/compile_ambi_converter.sh diff --git a/lib_util/ambi_convert.c b/lib_util/ambi_convert.c index 90fa692a4..53d0b2204 100644 --- a/lib_util/ambi_convert.c +++ b/lib_util/ambi_convert.c @@ -368,7 +368,7 @@ AMBI_CONVERT_ERROR renormalize_channels( Word64 tmp; tmp = W_mult0_32_32( in[i_chan][i], conversion_factor ); tmp = W_shr( tmp, Q29 ); - out[i_chan][i] = W_extract_h( tmp ); + out[i_chan][i] = W_extract_l( tmp ); } } diff --git a/scripts/compile_ambi_converter.sh b/scripts/compile_ambi_converter.sh new file mode 100644 index 000000000..39f084c29 --- /dev/null +++ b/scripts/compile_ambi_converter.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +rm -r ambi_converter +cc ambi_converter.c -o ambi_converter -I../lib_util/ -I../lib_com/ -I../lib_debug/ -I../lib_enc/ -I../lib_dec/ -I../lib_rend/ -I../lib_isar -I../lib_lc3plus -L../ -livasutil -lm -- GitLab From 93a87de3c3c87f9f1500dd6aa7e66ce81f2fb49b Mon Sep 17 00:00:00 2001 From: Thomas Dettbarn Date: Tue, 2 Sep 2025 11:29:16 +0200 Subject: [PATCH 04/10] reduced the bitwidth fron 32 to 16 bit for the ambisonic converter. --- lib_util/ambi_convert.c | 27 ++++++++++++++------------- lib_util/ambi_convert.h | 12 ++++++------ 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/lib_util/ambi_convert.c b/lib_util/ambi_convert.c index 53d0b2204..aa6753659 100644 --- a/lib_util/ambi_convert.c +++ b/lib_util/ambi_convert.c @@ -34,9 +34,8 @@ #include #include "ambi_convert.h" -#define THISQ Q29 - #define ONE_1_Q29 536870912l /* 1.0f */ +#define ONE_OVER_2_Q29 268435456 /* 1.0f/2.0f */ #define SQRT_2_Q29 759250112l /* sqrtf(2.0f) */ #define SQRT_3_Q29 929887680l /* sqrtf(3.0f) */ @@ -129,16 +128,16 @@ static const int16_t REORDER_ACN_SID[AMBI_MAX_CHANNELS] = { 0, --------------------------------------------------------------------------*/ AMBI_CONVERT_ERROR convert_ambi_format( - Word32 *in[], /* i: input ambisonics channels */ - Word32 *out[], /* o: output ambisonics channels */ + Word16 *in[], /* i: input ambisonics channels */ + Word16 *out[], /* o: output ambisonics channels */ int16_t order, /* i: ambisonics order */ AMBI_FMT in_format, /* i: input ambisonics format */ AMBI_FMT out_format /* i: output ambisonics format */ ) { - Word32 tmp[AMBI_MAX_CHANNELS * L_FRAME48k]; - Word32 *p_tmp[AMBI_MAX_CHANNELS]; + Word16 tmp[AMBI_MAX_CHANNELS * L_FRAME48k]; + Word16 *p_tmp[AMBI_MAX_CHANNELS]; AMBI_CONVERT_ERROR err = AMBI_CONVERT_OK; AMBI_CHANNEL_ORDER ch_ord_in = AMBI_CHANNEL_ORDER_ACN; @@ -304,8 +303,8 @@ AMBI_CONVERT_ERROR convert_ambi_format( --------------------------------------------------------------------------*/ AMBI_CONVERT_ERROR renormalize_channels( - Word32 *in[], /* i: input ambisonics channels */ - Word32 *out[], /* o: output ambisonics channels */ + Word16 *in[], /* i: input ambisonics channels */ + Word16 *out[], /* o: output ambisonics channels */ int16_t order, /* i: ambisonics order */ AMBI_CHANNEL_NORM in_format, /* i: input ambisonics format */ AMBI_CHANNEL_NORM out_format /* i: output ambisonics format */ @@ -315,6 +314,7 @@ AMBI_CONVERT_ERROR renormalize_channels( int16_t i_chan, i; const Word32 *conversion_table = 0; + /* conversion factors are applied on the channels assuming that they are still/already in ACN order */ if ( in_format == AMBI_NORM_SN3D ) { @@ -366,9 +366,10 @@ AMBI_CONVERT_ERROR renormalize_channels( for ( i = 0; i < L_FRAME48k; i++ ) { Word64 tmp; - tmp = W_mult0_32_32( in[i_chan][i], conversion_factor ); + tmp = W_mult0_32_32( (Word32)in[i_chan][i], conversion_factor ); + /* tmp = W_add( tmp, ONE_OVER_2_Q29); */ /* rounding up */ tmp = W_shr( tmp, Q29 ); - out[i_chan][i] = W_extract_l( tmp ); + out[i_chan][i] = extract_l( W_extract_l( tmp ) ); } } @@ -382,8 +383,8 @@ AMBI_CONVERT_ERROR renormalize_channels( --------------------------------------------------------------------------*/ AMBI_CONVERT_ERROR reorder_channels( - Word32 *in[], /* i: input ambisonics channels */ - Word32 *out[], /* o: output ambisonics channels */ + Word16 *in[], /* i: input ambisonics channels */ + Word16 *out[], /* o: output ambisonics channels */ int16_t order, /* i: ambisonics order */ AMBI_CHANNEL_ORDER in_format, /* i: input ambisonics format */ AMBI_CHANNEL_ORDER out_format /* i: output ambisonics format */ @@ -391,7 +392,7 @@ AMBI_CONVERT_ERROR reorder_channels( { int16_t n_chan = i_mult2( add( order, 1 ), add( order, 1 ) ); int16_t i_chan, i; - Word32 tmp[AMBI_MAX_CHANNELS]; + Word16 tmp[AMBI_MAX_CHANNELS]; const int16_t *idx_table = 0; if ( in_format == AMBI_CHANNEL_ORDER_ACN ) diff --git a/lib_util/ambi_convert.h b/lib_util/ambi_convert.h index 2b1f4480a..befdfc629 100644 --- a/lib_util/ambi_convert.h +++ b/lib_util/ambi_convert.h @@ -77,24 +77,24 @@ typedef enum } AMBI_CONVERT_ERROR; AMBI_CONVERT_ERROR convert_ambi_format( - Word32 *in[], /* i: input ambisonics channels */ - Word32 *out[], /* o: output ambisonics channels */ + Word16 *in[], /* i: input ambisonics channels */ + Word16 *out[], /* o: output ambisonics channels */ int16_t order, /* i: ambisonics order */ AMBI_FMT in_format, /* i: input ambisonics format */ AMBI_FMT out_format /* i: output ambisonics format */ ); AMBI_CONVERT_ERROR renormalize_channels( - Word32 *in[], /* i: input ambisonics channels */ - Word32 *out[], /* o: output ambisonics channels */ + Word16 *in[], /* i: input ambisonics channels */ + Word16 *out[], /* o: output ambisonics channels */ int16_t order, /* i: ambisonics order */ AMBI_CHANNEL_NORM in_format, /* i: input ambisonics format */ AMBI_CHANNEL_NORM out_format /* i: output ambisonics format */ ); AMBI_CONVERT_ERROR reorder_channels( - Word32 *in[], /* i: input ambisonics channels */ - Word32 *out[], /* o: output ambisonics channels */ + Word16 *in[], /* i: input ambisonics channels */ + Word16 *out[], /* o: output ambisonics channels */ int16_t order, /* i: ambisonics order */ AMBI_CHANNEL_ORDER in_format, /* i: input ambisonics format */ AMBI_CHANNEL_ORDER out_format /* i: output ambisonics format */ -- GitLab From bb274d8aa717f23c903f6c1ef61daa21baa9f38d Mon Sep 17 00:00:00 2001 From: Thomas Dettbarn Date: Tue, 2 Sep 2025 11:39:15 +0200 Subject: [PATCH 05/10] applied the clang patch. --- lib_util/ambi_convert.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib_util/ambi_convert.c b/lib_util/ambi_convert.c index aa6753659..ade8f8d5a 100644 --- a/lib_util/ambi_convert.c +++ b/lib_util/ambi_convert.c @@ -34,8 +34,8 @@ #include #include "ambi_convert.h" -#define ONE_1_Q29 536870912l /* 1.0f */ -#define ONE_OVER_2_Q29 268435456 /* 1.0f/2.0f */ +#define ONE_1_Q29 536870912l /* 1.0f */ +#define ONE_OVER_2_Q29 268435456l /* 1.0f/2.0f */ #define SQRT_2_Q29 759250112l /* sqrtf(2.0f) */ #define SQRT_3_Q29 929887680l /* sqrtf(3.0f) */ @@ -366,7 +366,7 @@ AMBI_CONVERT_ERROR renormalize_channels( for ( i = 0; i < L_FRAME48k; i++ ) { Word64 tmp; - tmp = W_mult0_32_32( (Word32)in[i_chan][i], conversion_factor ); + tmp = W_mult0_32_32( (Word32) in[i_chan][i], conversion_factor ); /* tmp = W_add( tmp, ONE_OVER_2_Q29); */ /* rounding up */ tmp = W_shr( tmp, Q29 ); out[i_chan][i] = extract_l( W_extract_l( tmp ) ); -- GitLab From c5078263d25e859922b0cb8a88cce65a1b83e287 Mon Sep 17 00:00:00 2001 From: Thomas Dettbarn Date: Tue, 2 Sep 2025 12:28:24 +0200 Subject: [PATCH 06/10] applied the clang patch. --- lib_util/ambi_convert.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_util/ambi_convert.c b/lib_util/ambi_convert.c index ade8f8d5a..6dc525365 100644 --- a/lib_util/ambi_convert.c +++ b/lib_util/ambi_convert.c @@ -35,7 +35,7 @@ #include "ambi_convert.h" #define ONE_1_Q29 536870912l /* 1.0f */ -#define ONE_OVER_2_Q29 268435456l /* 1.0f/2.0f */ +#define ONE_OVER_2_Q29 268435456l /* 1.0f/2.0f */ #define SQRT_2_Q29 759250112l /* sqrtf(2.0f) */ #define SQRT_3_Q29 929887680l /* sqrtf(3.0f) */ -- GitLab From ed39cf696da659958fe4f53810ea7276ed5e0b5c Mon Sep 17 00:00:00 2001 From: Thomas Dettbarn Date: Tue, 2 Sep 2025 12:47:23 +0200 Subject: [PATCH 07/10] applied the basop instrumentalisation. --- lib_util/ambi_convert.c | 145 ++++++++++++++++++++++++++-------------- 1 file changed, 95 insertions(+), 50 deletions(-) diff --git a/lib_util/ambi_convert.c b/lib_util/ambi_convert.c index 6dc525365..dfac4d957 100644 --- a/lib_util/ambi_convert.c +++ b/lib_util/ambi_convert.c @@ -146,149 +146,180 @@ AMBI_CONVERT_ERROR convert_ambi_format( AMBI_CHANNEL_NORM ch_norm_in = AMBI_NORM_SN3D; AMBI_CHANNEL_NORM ch_norm_out = AMBI_NORM_SN3D; + Word16 i,j; + assert( order <= 3 ); if ( in_format != AMBI_FMT_ACN_SN3D && out_format != AMBI_FMT_ACN_SN3D ) { assert( 0 && "Conversion only supported to and from ACN-SN3D" ); } - - for ( int16_t j = 0; j < AMBI_MAX_CHANNELS; j++ ) + i = 0; + move16(); + FOR( j = 0; j < AMBI_MAX_CHANNELS; j++ ) { - p_tmp[j] = &tmp[j * L_FRAME48k]; + p_tmp[j] = &tmp[i]; + move32(); + i = add( i, L_FRAME48k ); } - switch ( in_format ) + SWITCH( in_format ) { case AMBI_FMT_ACN_SN3D: ch_ord_in = AMBI_CHANNEL_ORDER_ACN; ch_norm_in = AMBI_NORM_SN3D; + move16(); + move16(); break; case AMBI_FMT_ACN_N3D: ch_ord_in = AMBI_CHANNEL_ORDER_ACN; ch_norm_in = AMBI_NORM_N3D; + move16(); + move16(); break; case AMBI_FMT_FM_MAXN: ch_ord_in = AMBI_CHANNEL_ORDER_FM; ch_norm_in = AMBI_NORM_MAXN; + move16(); + move16(); break; case AMBI_FMT_FM_FM: ch_ord_in = AMBI_CHANNEL_ORDER_FM; ch_norm_in = AMBI_NORM_FM; + move16(); + move16(); break; case AMBI_FMT_SID_SN3D: ch_ord_in = AMBI_CHANNEL_ORDER_SID; ch_norm_in = AMBI_NORM_SN3D; + move16(); + move16(); break; case AMBI_FMT_SID_N3D: ch_ord_in = AMBI_CHANNEL_ORDER_SID; ch_norm_in = AMBI_NORM_N3D; + move16(); + move16(); break; default: return AMBI_CONVERT_UNSUPPORTED_CONVERSION; } - switch ( out_format ) + SWITCH( out_format ) { case AMBI_FMT_ACN_SN3D: ch_ord_out = AMBI_CHANNEL_ORDER_ACN; ch_norm_out = AMBI_NORM_SN3D; + move16(); + move16(); break; case AMBI_FMT_ACN_N3D: ch_ord_out = AMBI_CHANNEL_ORDER_ACN; ch_norm_out = AMBI_NORM_N3D; + move16(); + move16(); break; case AMBI_FMT_FM_MAXN: ch_ord_out = AMBI_CHANNEL_ORDER_FM; ch_norm_out = AMBI_NORM_MAXN; + move16(); + move16(); break; case AMBI_FMT_FM_FM: ch_ord_out = AMBI_CHANNEL_ORDER_FM; ch_norm_out = AMBI_NORM_FM; + move16(); + move16(); break; case AMBI_FMT_SID_SN3D: ch_ord_out = AMBI_CHANNEL_ORDER_SID; ch_norm_out = AMBI_NORM_SN3D; + move16(); + move16(); break; case AMBI_FMT_SID_N3D: ch_ord_out = AMBI_CHANNEL_ORDER_SID; ch_norm_out = AMBI_NORM_N3D; + move16(); + move16(); break; default: return AMBI_CONVERT_UNSUPPORTED_CONVERSION; } - if ( in_format == AMBI_FMT_ACN_SN3D && ch_norm_in != ch_norm_out ) + IF( in_format == AMBI_FMT_ACN_SN3D && ch_norm_in != ch_norm_out ) { - if ( ch_ord_in != ch_ord_out ) + IF( ch_ord_in != ch_ord_out ) { - if ( ( err = renormalize_channels( in, p_tmp, order, ch_norm_in, ch_norm_out ) ) != AMBI_CONVERT_OK ) + IF( ( err = renormalize_channels( in, p_tmp, order, ch_norm_in, ch_norm_out ) ) != AMBI_CONVERT_OK ) { return err; } - if ( ( err = reorder_channels( p_tmp, out, order, ch_ord_in, ch_ord_out ) ) != AMBI_CONVERT_OK ) + IF( ( err = reorder_channels( p_tmp, out, order, ch_ord_in, ch_ord_out ) ) != AMBI_CONVERT_OK ) { return err; } } - else + ELSE { - if ( ( err = renormalize_channels( in, out, order, ch_norm_in, ch_norm_out ) ) != AMBI_CONVERT_OK ) + IF( ( err = renormalize_channels( in, out, order, ch_norm_in, ch_norm_out ) ) != AMBI_CONVERT_OK ) { return err; } } } - else if ( in_format == AMBI_FMT_ACN_SN3D && ch_ord_in != ch_ord_out ) + ELSE IF( in_format == AMBI_FMT_ACN_SN3D && ch_ord_in != ch_ord_out ) { - if ( ( err = reorder_channels( in, out, order, ch_ord_in, ch_ord_out ) ) != AMBI_CONVERT_OK ) + IF( ( err = reorder_channels( in, out, order, ch_ord_in, ch_ord_out ) ) != AMBI_CONVERT_OK ) { return err; } } - else if ( out_format == AMBI_FMT_ACN_SN3D && ch_norm_in != ch_norm_out ) + ELSE IF( out_format == AMBI_FMT_ACN_SN3D && ch_norm_in != ch_norm_out ) { - if ( ch_ord_in != ch_ord_out ) + IF( ch_ord_in != ch_ord_out ) { - if ( ( err = reorder_channels( in, p_tmp, order, ch_ord_in, ch_ord_out ) ) != AMBI_CONVERT_OK ) + IF( ( err = reorder_channels( in, p_tmp, order, ch_ord_in, ch_ord_out ) ) != AMBI_CONVERT_OK ) { return err; } - if ( ( err = renormalize_channels( p_tmp, out, order, ch_norm_in, ch_norm_out ) ) != AMBI_CONVERT_OK ) + IF( ( err = renormalize_channels( p_tmp, out, order, ch_norm_in, ch_norm_out ) ) != AMBI_CONVERT_OK ) { return err; } } - else + ELSE { - if ( ( err = renormalize_channels( in, out, order, ch_norm_in, ch_norm_out ) ) != AMBI_CONVERT_OK ) + IF( ( err = renormalize_channels( in, out, order, ch_norm_in, ch_norm_out ) ) != AMBI_CONVERT_OK ) { return err; } } } - else if ( out_format == AMBI_FMT_ACN_SN3D && ch_ord_in != ch_ord_out ) + ELSE IF( out_format == AMBI_FMT_ACN_SN3D && ch_ord_in != ch_ord_out ) { - if ( ( err = reorder_channels( in, out, order, ch_ord_in, ch_ord_out ) ) != AMBI_CONVERT_OK ) + IF( ( err = reorder_channels( in, out, order, ch_ord_in, ch_ord_out ) ) != AMBI_CONVERT_OK ) { return err; } } - else if ( out_format == AMBI_FMT_ACN_SN3D && in_format == AMBI_FMT_ACN_SN3D ) + ELSE IF( out_format == AMBI_FMT_ACN_SN3D && in_format == AMBI_FMT_ACN_SN3D ) { int16_t i_chan = 0; int16_t n_chan = i_mult2( add( order, 1 ), add( order, 1 ) ); - for ( i_chan = 0; i_chan < n_chan; i_chan++ ) + FOR( i_chan = 0; i_chan < n_chan; i_chan++ ) { int16_t i = 0; - for ( i = 0; i < L_FRAME48k; i++ ) + move16(); + FOR( i = 0; i < L_FRAME48k; i++ ) { out[i_chan][i] = in[i_chan][i]; + move16(); } } } - else + ELSE { assert( 0 && "This should never happen!" ); } @@ -316,54 +347,61 @@ AMBI_CONVERT_ERROR renormalize_channels( /* conversion factors are applied on the channels assuming that they are still/already in ACN order */ - if ( in_format == AMBI_NORM_SN3D ) + IF( in_format == AMBI_NORM_SN3D ) { - if ( out_format == AMBI_NORM_N3D ) + IF( out_format == AMBI_NORM_N3D ) { conversion_table = SN3D_N3D; + move32(); } - else if ( out_format == AMBI_NORM_MAXN ) + ELSE IF( out_format == AMBI_NORM_MAXN ) { conversion_table = SN3D_MAXN; + move32(); } - else if ( out_format == AMBI_NORM_FM ) + ELSE IF( out_format == AMBI_NORM_FM ) { conversion_table = SN3D_FM; + move32(); } - else + ELSE { return AMBI_CONVERT_UNSUPPORTED_CONVERSION; } } - else if ( out_format == AMBI_NORM_SN3D ) + ELSE IF( out_format == AMBI_NORM_SN3D ) { - if ( in_format == AMBI_NORM_N3D ) + IF( in_format == AMBI_NORM_N3D ) { conversion_table = N3D_SN3D; + move32(); } - else if ( in_format == AMBI_NORM_MAXN ) + ELSE IF( in_format == AMBI_NORM_MAXN ) { conversion_table = MAXN_SN3D; + move32(); } - else if ( in_format == AMBI_NORM_FM ) + ELSE IF( in_format == AMBI_NORM_FM ) { conversion_table = FM_SN3D; + move32(); } - else + ELSE { return AMBI_CONVERT_UNSUPPORTED_CONVERSION; } } - else + ELSE { return AMBI_CONVERT_UNSUPPORTED_CONVERSION; } - for ( i_chan = 0; i_chan < n_chan; i_chan++ ) + FOR( i_chan = 0; i_chan < n_chan; i_chan++ ) { Word32 conversion_factor = conversion_table[i_chan]; - for ( i = 0; i < L_FRAME48k; i++ ) + move32(); + FOR( i = 0; i < L_FRAME48k; i++ ) { Word64 tmp; tmp = W_mult0_32_32( (Word32) in[i_chan][i], conversion_factor ); @@ -395,51 +433,58 @@ AMBI_CONVERT_ERROR reorder_channels( Word16 tmp[AMBI_MAX_CHANNELS]; const int16_t *idx_table = 0; - if ( in_format == AMBI_CHANNEL_ORDER_ACN ) + IF( in_format == AMBI_CHANNEL_ORDER_ACN ) { - if ( out_format == AMBI_CHANNEL_ORDER_FM ) + IF( out_format == AMBI_CHANNEL_ORDER_FM ) { idx_table = REORDER_ACN_FM; + move16(); } - else if ( out_format == AMBI_CHANNEL_ORDER_SID ) + ELSE IF( out_format == AMBI_CHANNEL_ORDER_SID ) { idx_table = REORDER_ACN_SID; + move16(); } - else + ELSE { return AMBI_CONVERT_UNSUPPORTED_CONVERSION; } } - else if ( out_format == AMBI_CHANNEL_ORDER_ACN ) + ELSE IF( out_format == AMBI_CHANNEL_ORDER_ACN ) { - if ( in_format == AMBI_CHANNEL_ORDER_FM ) + IF( in_format == AMBI_CHANNEL_ORDER_FM ) { idx_table = REORDER_FM_ACN; + move16(); } - else if ( in_format == AMBI_CHANNEL_ORDER_SID ) + ELSE IF( in_format == AMBI_CHANNEL_ORDER_SID ) { idx_table = REORDER_SID_ACN; + move16(); } - else + ELSE { return AMBI_CONVERT_UNSUPPORTED_CONVERSION; } } - else + ELSE { return AMBI_CONVERT_UNSUPPORTED_CONVERSION; } - for ( i = 0; i < L_FRAME48k; i++ ) + FOR( i = 0; i < L_FRAME48k; i++ ) { - for ( i_chan = 0; i_chan < n_chan; i_chan++ ) + FOR( i_chan = 0; i_chan < n_chan; i_chan++ ) { int16_t idx = idx_table[i_chan]; + move16(); tmp[i_chan] = in[idx][i]; + move16(); } - for ( i_chan = 0; i_chan < n_chan; i_chan++ ) + FOR( i_chan = 0; i_chan < n_chan; i_chan++ ) { out[i_chan][i] = tmp[i_chan]; + move16(); } } -- GitLab From dee64c132beb46caf36201988c4214732720ac47 Mon Sep 17 00:00:00 2001 From: Thomas Dettbarn Date: Tue, 2 Sep 2025 12:52:39 +0200 Subject: [PATCH 08/10] applied the clang patch. --- lib_util/ambi_convert.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_util/ambi_convert.c b/lib_util/ambi_convert.c index dfac4d957..fa1cfa4f6 100644 --- a/lib_util/ambi_convert.c +++ b/lib_util/ambi_convert.c @@ -146,7 +146,7 @@ AMBI_CONVERT_ERROR convert_ambi_format( AMBI_CHANNEL_NORM ch_norm_in = AMBI_NORM_SN3D; AMBI_CHANNEL_NORM ch_norm_out = AMBI_NORM_SN3D; - Word16 i,j; + Word16 i, j; assert( order <= 3 ); -- GitLab From 8950f44aeebecfa81fc58a9cd6039cc9e4b0ece9 Mon Sep 17 00:00:00 2001 From: Thomas Dettbarn Date: Wed, 3 Sep 2025 11:18:11 +0200 Subject: [PATCH 09/10] the ambi convert function reports a AMBI_CONVERT_CLIPPING_DETECTED error in case the output does no longer fit into 16 bit. --- lib_util/ambi_convert.c | 18 +++++++++++++++--- lib_util/ambi_convert.h | 3 ++- scripts/compile_ambi_converter.sh | 4 ---- 3 files changed, 17 insertions(+), 8 deletions(-) delete mode 100644 scripts/compile_ambi_converter.sh diff --git a/lib_util/ambi_convert.c b/lib_util/ambi_convert.c index fa1cfa4f6..6846a9270 100644 --- a/lib_util/ambi_convert.c +++ b/lib_util/ambi_convert.c @@ -32,6 +32,7 @@ #include #include +#include "wmc_auto.h" #include "ambi_convert.h" #define ONE_1_Q29 536870912l /* 1.0f */ @@ -344,6 +345,11 @@ AMBI_CONVERT_ERROR renormalize_channels( int16_t n_chan = i_mult2( add( order, 1 ), add( order, 1 ) ); int16_t i_chan, i; const Word32 *conversion_table = 0; + Word32 minval = 0; + Word32 maxval = 0; + move32(); + move32(); + move32(); /* conversion factors are applied on the channels assuming that they are still/already in ACN order */ @@ -400,17 +406,23 @@ AMBI_CONVERT_ERROR renormalize_channels( FOR( i_chan = 0; i_chan < n_chan; i_chan++ ) { Word32 conversion_factor = conversion_table[i_chan]; + Word32 outval; move32(); FOR( i = 0; i < L_FRAME48k; i++ ) { Word64 tmp; tmp = W_mult0_32_32( (Word32) in[i_chan][i], conversion_factor ); /* tmp = W_add( tmp, ONE_OVER_2_Q29); */ /* rounding up */ - tmp = W_shr( tmp, Q29 ); - out[i_chan][i] = extract_l( W_extract_l( tmp ) ); + outval = W_extract_l( W_shr( tmp, Q29 ) ); + minval = L_min( minval, outval ); + maxval = L_min( maxval, outval ); + out[i_chan][i] = extract_l( outval ); } } - + IF( ( minval < MIN16B ) || ( maxval > MAX16B ) ) + { + return AMBI_CONVERT_CLIPPING_DETECTED; + } return AMBI_CONVERT_OK; } diff --git a/lib_util/ambi_convert.h b/lib_util/ambi_convert.h index befdfc629..a6e7cb1ae 100644 --- a/lib_util/ambi_convert.h +++ b/lib_util/ambi_convert.h @@ -73,7 +73,8 @@ typedef enum typedef enum { AMBI_CONVERT_OK = 0, - AMBI_CONVERT_UNSUPPORTED_CONVERSION + AMBI_CONVERT_UNSUPPORTED_CONVERSION, + AMBI_CONVERT_CLIPPING_DETECTED } AMBI_CONVERT_ERROR; AMBI_CONVERT_ERROR convert_ambi_format( diff --git a/scripts/compile_ambi_converter.sh b/scripts/compile_ambi_converter.sh deleted file mode 100644 index 39f084c29..000000000 --- a/scripts/compile_ambi_converter.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -rm -r ambi_converter -cc ambi_converter.c -o ambi_converter -I../lib_util/ -I../lib_com/ -I../lib_debug/ -I../lib_enc/ -I../lib_dec/ -I../lib_rend/ -I../lib_isar -I../lib_lc3plus -L../ -livasutil -lm -- GitLab From ca21bc6655f71a26c9c05186f9b1d73a8564867f Mon Sep 17 00:00:00 2001 From: Thomas Dettbarn Date: Wed, 3 Sep 2025 14:16:12 +0200 Subject: [PATCH 10/10] documented the format of the input and output samples for the ambi_converter as Q0 in the comments. --- lib_util/ambi_convert.c | 30 +++++++++++++++--------------- lib_util/ambi_convert.h | 30 +++++++++++++++--------------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/lib_util/ambi_convert.c b/lib_util/ambi_convert.c index 6846a9270..0bf2bf226 100644 --- a/lib_util/ambi_convert.c +++ b/lib_util/ambi_convert.c @@ -129,11 +129,11 @@ static const int16_t REORDER_ACN_SID[AMBI_MAX_CHANNELS] = { 0, --------------------------------------------------------------------------*/ AMBI_CONVERT_ERROR convert_ambi_format( - Word16 *in[], /* i: input ambisonics channels */ - Word16 *out[], /* o: output ambisonics channels */ - int16_t order, /* i: ambisonics order */ - AMBI_FMT in_format, /* i: input ambisonics format */ - AMBI_FMT out_format /* i: output ambisonics format */ + Word16 *in[], /* i: input ambisonics channels, Q0 */ + Word16 *out[], /* o: output ambisonics channels, Q0 */ + int16_t order, /* i: ambisonics order */ + AMBI_FMT in_format, /* i: input ambisonics format */ + AMBI_FMT out_format /* i: output ambisonics format */ ) { @@ -335,11 +335,11 @@ AMBI_CONVERT_ERROR convert_ambi_format( --------------------------------------------------------------------------*/ AMBI_CONVERT_ERROR renormalize_channels( - Word16 *in[], /* i: input ambisonics channels */ - Word16 *out[], /* o: output ambisonics channels */ - int16_t order, /* i: ambisonics order */ - AMBI_CHANNEL_NORM in_format, /* i: input ambisonics format */ - AMBI_CHANNEL_NORM out_format /* i: output ambisonics format */ + Word16 *in[], /* i: input ambisonics channels, Q0 */ + Word16 *out[], /* o: output ambisonics channels, Q0 */ + int16_t order, /* i: ambisonics order */ + AMBI_CHANNEL_NORM in_format, /* i: input ambisonics format */ + AMBI_CHANNEL_NORM out_format /* i: output ambisonics format */ ) { int16_t n_chan = i_mult2( add( order, 1 ), add( order, 1 ) ); @@ -433,11 +433,11 @@ AMBI_CONVERT_ERROR renormalize_channels( --------------------------------------------------------------------------*/ AMBI_CONVERT_ERROR reorder_channels( - Word16 *in[], /* i: input ambisonics channels */ - Word16 *out[], /* o: output ambisonics channels */ - int16_t order, /* i: ambisonics order */ - AMBI_CHANNEL_ORDER in_format, /* i: input ambisonics format */ - AMBI_CHANNEL_ORDER out_format /* i: output ambisonics format */ + Word16 *in[], /* i: input ambisonics channels, Q0 */ + Word16 *out[], /* o: output ambisonics channels, Q0 */ + int16_t order, /* i: ambisonics order */ + AMBI_CHANNEL_ORDER in_format, /* i: input ambisonics format */ + AMBI_CHANNEL_ORDER out_format /* i: output ambisonics format */ ) { int16_t n_chan = i_mult2( add( order, 1 ), add( order, 1 ) ); diff --git a/lib_util/ambi_convert.h b/lib_util/ambi_convert.h index a6e7cb1ae..207bd276f 100644 --- a/lib_util/ambi_convert.h +++ b/lib_util/ambi_convert.h @@ -78,26 +78,26 @@ typedef enum } AMBI_CONVERT_ERROR; AMBI_CONVERT_ERROR convert_ambi_format( - Word16 *in[], /* i: input ambisonics channels */ - Word16 *out[], /* o: output ambisonics channels */ - int16_t order, /* i: ambisonics order */ - AMBI_FMT in_format, /* i: input ambisonics format */ - AMBI_FMT out_format /* i: output ambisonics format */ + Word16 *in[], /* i: input ambisonics channels, Q0 */ + Word16 *out[], /* o: output ambisonics channels, Q0 */ + int16_t order, /* i: ambisonics order */ + AMBI_FMT in_format, /* i: input ambisonics format */ + AMBI_FMT out_format /* i: output ambisonics format */ ); AMBI_CONVERT_ERROR renormalize_channels( - Word16 *in[], /* i: input ambisonics channels */ - Word16 *out[], /* o: output ambisonics channels */ - int16_t order, /* i: ambisonics order */ - AMBI_CHANNEL_NORM in_format, /* i: input ambisonics format */ - AMBI_CHANNEL_NORM out_format /* i: output ambisonics format */ + Word16 *in[], /* i: input ambisonics channels, Q0 */ + Word16 *out[], /* o: output ambisonics channels, Q0 */ + int16_t order, /* i: ambisonics order */ + AMBI_CHANNEL_NORM in_format, /* i: input ambisonics format */ + AMBI_CHANNEL_NORM out_format /* i: output ambisonics format */ ); AMBI_CONVERT_ERROR reorder_channels( - Word16 *in[], /* i: input ambisonics channels */ - Word16 *out[], /* o: output ambisonics channels */ - int16_t order, /* i: ambisonics order */ - AMBI_CHANNEL_ORDER in_format, /* i: input ambisonics format */ - AMBI_CHANNEL_ORDER out_format /* i: output ambisonics format */ + Word16 *in[], /* i: input ambisonics channels, Q0 */ + Word16 *out[], /* o: output ambisonics channels, Q0 */ + int16_t order, /* i: ambisonics order */ + AMBI_CHANNEL_ORDER in_format, /* i: input ambisonics format */ + AMBI_CHANNEL_ORDER out_format /* i: output ambisonics format */ ); #endif -- GitLab