Line data Source code
1 : /******************************************************************************************************
2 :
3 : (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
4 : Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
5 : Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
6 : Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
7 : contributors to this repository. All Rights Reserved.
8 :
9 : This software is protected by copyright law and by international treaties.
10 : The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
11 : Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
12 : Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
13 : Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
14 : contributors to this repository retain full ownership rights in their respective contributions in
15 : the software. This notice grants no license of any kind, including but not limited to patent
16 : license, nor is any license granted by implication, estoppel or otherwise.
17 :
18 : Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
19 : contributions.
20 :
21 : This software is provided "AS IS", without any express or implied warranties. The software is in the
22 : development stage. It is intended exclusively for experts who have experience with such software and
23 : solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
24 : and fitness for a particular purpose are hereby disclaimed and excluded.
25 :
26 : Any dispute, controversy or claim arising under or in relation to providing this software shall be
27 : submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
28 : accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
29 : the United Nations Convention on Contracts on the International Sales of Goods.
30 :
31 : *******************************************************************************************************/
32 :
33 : #include <assert.h>
34 : #include <stdint.h>
35 : #include <math.h>
36 : #include "options.h"
37 : #include "cnst.h"
38 : #include "ivas_cnst.h"
39 : #include "rom_com.h"
40 : #include "prot_fx.h"
41 : #include "ivas_stat_com.h"
42 : #include "ivas_rom_com.h"
43 : #include "wmc_auto.h"
44 : #include "ivas_prot_fx.h"
45 :
46 : /*-------------------------------------------------------------------*
47 : * ivas_sba_config()
48 : *
49 : * Configure SBA coding
50 : *-------------------------------------------------------------------*/
51 :
52 139766 : void ivas_sba_config_fx(
53 : const Word32 sba_total_brate, /* i : SBA total bitrate */
54 : Word16 sba_order, /* i : Ambisonic (SBA) order */
55 : Word16 nb_channels, /* i : Number of ambisonic channels */
56 : Word16 *nchan_transport, /* o : number of transport channels */
57 : const Word16 sba_planar, /* i : SBA Planar flag */
58 : Word16 *nSCE, /* o : number of SCEs */
59 : Word16 *nCPE, /* o : number of CPEs */
60 : Word16 *element_mode /* o : element mode of the core coder */
61 : )
62 : {
63 139766 : test();
64 139766 : IF( sba_order < 0 && nb_channels < 0 )
65 : {
66 0 : assert( 0 && "Either order or number of channels must be positive" );
67 : }
68 139766 : ELSE IF( sba_order < 0 )
69 : {
70 0 : sba_order = ivas_sba_get_order_fx( nb_channels, sba_planar );
71 : }
72 139766 : ELSE IF( nb_channels < 0 )
73 : {
74 139766 : nb_channels = ivas_sba_get_nchan_fx( sba_order, sba_planar );
75 : }
76 : ELSE
77 : {
78 0 : IF( sba_planar )
79 : {
80 0 : assert( ( EQ_16( add( shl( sba_order, 1 ), 1 ), nb_channels ) ) && "Order and number of channels do not correspond!" );
81 : }
82 : ELSE
83 : {
84 0 : assert( ( EQ_16( mult( add( sba_order, 1 ), add( sba_order, 1 ) ), nb_channels ) ) && "Order and number of channels do not correspond!" );
85 : }
86 : }
87 :
88 139766 : IF( nchan_transport != NULL )
89 : {
90 139766 : *nchan_transport = ivas_get_sba_num_TCs_fx( sba_total_brate, sba_order );
91 139766 : move16();
92 : }
93 :
94 : /* Configure core coder number of elements*/
95 139766 : test();
96 139766 : test();
97 139766 : IF( nchan_transport != NULL && nSCE != NULL && nCPE != NULL )
98 : {
99 139766 : IF( EQ_16( *nchan_transport, 1 ) )
100 : {
101 37115 : *nSCE = 1;
102 37115 : move16();
103 37115 : *nCPE = 0;
104 37115 : move16();
105 37115 : *element_mode = IVAS_SCE;
106 37115 : move16();
107 : }
108 : ELSE
109 : {
110 102651 : *nSCE = 0;
111 102651 : move16();
112 102651 : *nCPE = shr( *nchan_transport, 1 );
113 102651 : move16();
114 102651 : IF( NE_16( i_mult( 2, ( *nCPE ) ), *nchan_transport ) )
115 : {
116 29215 : *nCPE = add( *nCPE, 1 );
117 29215 : move16();
118 : }
119 102651 : *element_mode = IVAS_CPE_MDCT;
120 102651 : move16();
121 : }
122 : }
123 :
124 139766 : return;
125 : }
126 :
127 :
128 : /*-------------------------------------------------------------------*
129 : * ivas_sba_get_order()
130 : *
131 : * Get Ambisonic order from number of ambisonic channels
132 : *-------------------------------------------------------------------*/
133 :
134 : /*! r: Ambisonic (SBA) order */
135 0 : Word16 ivas_sba_get_order_fx(
136 : const Word16 nb_channels, /* i : Number of ambisonic channels */
137 : const Word16 sba_planar /* i : SBA Planar flag */
138 : )
139 : {
140 : Word16 sba_order;
141 :
142 : /* sba_order = (int16_t) sqrtf( (float) nb_channels ) - 1 */
143 0 : Word16 sba_order_non_sba_planar[MAX_INPUT_CHANNELS] = { 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3 };
144 0 : move16();
145 0 : move16();
146 0 : move16();
147 0 : move16();
148 0 : move16();
149 0 : move16();
150 0 : move16();
151 0 : move16();
152 0 : move16();
153 0 : move16();
154 0 : move16();
155 0 : move16();
156 0 : move16();
157 0 : move16();
158 0 : move16();
159 0 : move16();
160 :
161 0 : IF( sba_planar )
162 : {
163 0 : sba_order = shr( sub( nb_channels, 1 ), 1 );
164 0 : assert( ( EQ_16( add( shl( sba_order, 1 ), 1 ), nb_channels ) ) && "Number of channels not supported in Planar SBA!" );
165 : }
166 : ELSE
167 : {
168 0 : sba_order = sba_order_non_sba_planar[nb_channels - 1];
169 0 : move16();
170 0 : assert( ( EQ_16( mult( add( sba_order, 1 ), add( sba_order, 1 ) ), nb_channels ) ) && "Number of channels not supported in SBA!" );
171 : }
172 :
173 0 : assert( ( sba_order <= 3 ) && "Error: SBA order must be <= 3!" );
174 :
175 0 : return ( sba_order );
176 : }
177 :
178 :
179 : /*-------------------------------------------------------------------*
180 : * ivas_sba_get_analysis_order()
181 : *
182 : * Get Ambisonic order used for analysis and coding
183 : *-------------------------------------------------------------------*/
184 :
185 : /*! r: Ambisonic (SBA) order used for analysis and coding */
186 144065 : Word16 ivas_sba_get_analysis_order_fx(
187 : const Word32 ivas_total_brate, /* i : IVAS total bitrate */
188 : const Word16 sba_order /* i : Ambisonic (SBA) order */
189 : )
190 : {
191 : Word16 sba_analysis_order;
192 :
193 144065 : sba_analysis_order = sba_order;
194 144065 : move16();
195 :
196 144065 : if ( LT_32( ivas_total_brate, SBA_MIN_BRATE_HOA ) )
197 : {
198 : /* Hard coding the sba_analysis_order as 1 as higher not supported below SBA_MIN_BRATE_HOA bitrate */
199 106474 : sba_analysis_order = SBA_FOA_ORDER;
200 106474 : move16();
201 : }
202 :
203 144065 : return sba_analysis_order;
204 : }
205 :
206 :
207 : /*-------------------------------------------------------------------*
208 : * ivas_sba_get_nchan()
209 : *
210 : * Get number of Ambisonic channels
211 : *-------------------------------------------------------------------*/
212 :
213 : /*! r: number of Ambisonic channels */
214 2035433 : Word16 ivas_sba_get_nchan_fx(
215 : const Word16 sba_order, /* i : Ambisonic (SBA) order */
216 : const Word16 sba_planar /* i : SBA planar flag */
217 : )
218 : {
219 : Word16 nb_channels;
220 :
221 2035433 : IF( sba_planar )
222 : {
223 8210 : nb_channels = add( shl( sba_order, 1 ), 1 );
224 : }
225 : ELSE
226 : {
227 2027223 : nb_channels = i_mult( add( sba_order, 1 ), add( sba_order, 1 ) );
228 : }
229 :
230 2035433 : return ( nb_channels );
231 : }
232 :
233 :
234 : /*-------------------------------------------------------------------*
235 : * ivas_sba_get_nchan_metadata()
236 : *
237 : * Get number of Ambisonic channels for metadata coding
238 : *-------------------------------------------------------------------*/
239 :
240 : /*! r: number of ambisonics metadata channels */
241 4611310 : Word16 ivas_sba_get_nchan_metadata_fx(
242 : const Word16 sba_order, /* i : Ambisonic (SBA) order */
243 : const Word32 ivas_total_brate /* i : IVAS total bitrate */
244 : )
245 : {
246 : Word16 nb_channels;
247 :
248 4611310 : IF( EQ_16( sba_order, SBA_FOA_ORDER ) )
249 : {
250 3414154 : nb_channels = FOA_CHANNELS;
251 3414154 : move16();
252 : }
253 : ELSE
254 : {
255 1197156 : IF( GE_32( ivas_total_brate, IVAS_512k ) )
256 : {
257 421666 : nb_channels = IVAS_SPAR_MAX_CH;
258 421666 : move16();
259 421666 : nb_channels = s_min( nb_channels, imult1616( add( sba_order, 1 ), add( sba_order, 1 ) ) );
260 : }
261 : ELSE
262 : {
263 : /* FOA + planar HOA */
264 775490 : nb_channels = add( FOA_CHANNELS, shl( sub( sba_order, 1 ), 1 ) );
265 : }
266 : }
267 :
268 4611310 : return ( nb_channels );
269 : }
270 :
271 : /*-------------------------------------------------------------------*
272 : * ivas_sba_get_spar_hoa_ch_ind()
273 : *
274 : *
275 : *-------------------------------------------------------------------*/
276 :
277 : /*! r: flag indicating to code SPAR HOA MD for all bands */
278 3625 : void ivas_sba_get_spar_hoa_ch_ind_fx(
279 : const Word16 num_md_chs, /* i : number of MD channels */
280 : const Word32 ivas_total_brate, /* i : IVAS total bitrate */
281 : Word16 HOA_md_ind[IVAS_SPAR_MAX_CH] )
282 : {
283 : Word16 ch;
284 : const Word16 *hoa_ind;
285 :
286 3625 : IF( GE_32( ivas_total_brate, IVAS_512k ) )
287 : {
288 228 : hoa_ind = HOA_keep_ind_spar512;
289 : }
290 : ELSE
291 : {
292 3397 : hoa_ind = HOA_keep_ind_spar;
293 : }
294 :
295 20414 : FOR( ch = 0; ch < num_md_chs; ch++ )
296 : {
297 16789 : HOA_md_ind[ch] = hoa_ind[ch];
298 16789 : move16();
299 : }
300 :
301 3625 : return;
302 : }
303 :
304 :
305 : /*-------------------------------------------------------------------*
306 : * ivas_sba_get_spar_hoa_md_flag()
307 : *
308 : * Get the flag to code SPAR HOA MD for all band
309 : *-------------------------------------------------------------------*/
310 :
311 3625 : void ivas_sba_get_spar_hoa_md_flag_fx(
312 : const Word16 sba_order, /* i : Ambisonic (SBA) order */
313 : const Word32 ivas_total_brate, /* i : IVAS total bitrate */
314 : Word16 *spar_hoa_md_flag,
315 : Word16 *spar_hoa_dirac2spar_md_flag )
316 : {
317 3625 : test();
318 3625 : IF( GT_16( sba_order, 1 ) && GE_32( ivas_total_brate, IVAS_256k ) )
319 : {
320 499 : *spar_hoa_md_flag = 1;
321 499 : move16();
322 : }
323 : ELSE
324 : {
325 3126 : *spar_hoa_md_flag = 0;
326 3126 : move16();
327 : }
328 :
329 3625 : test();
330 3625 : IF( GT_16( sba_order, 1 ) && GE_32( ivas_total_brate, IVAS_512k ) )
331 : {
332 183 : *spar_hoa_dirac2spar_md_flag = 0;
333 183 : move16();
334 : }
335 : ELSE
336 : {
337 3442 : *spar_hoa_dirac2spar_md_flag = 1;
338 3442 : move16();
339 : }
340 :
341 3625 : return;
342 : }
343 :
344 :
345 : /*-------------------------------------------------------------------*
346 : * ivas_sba_zero_vert_comp()
347 : *
348 : * Zero vertical Ambisonics components
349 : *-------------------------------------------------------------------*/
350 20500 : void ivas_sba_zero_vert_comp_fx(
351 : Word32 *sba_data[], /* i : SBA signals q_data */
352 : const Word16 sba_order, /* i : SBA order */
353 : const Word16 sba_planar, /* i : SBA planar flag */
354 : const Word16 input_frame /* i : frame length */
355 : )
356 : {
357 : Word16 i, j;
358 :
359 : /* Channels in the range i^2+1 to (i+1)^2 -1 are zeroed (retain only first and last channel for that order) */
360 48280 : FOR( i = 1; i <= sba_order; i++ )
361 : {
362 27780 : test();
363 : /* Keep Z if not planar */
364 27780 : IF( !sba_planar && EQ_16( i, 1 ) )
365 : {
366 0 : CONTINUE;
367 : }
368 :
369 75400 : FOR( j = ( i * i + 1 ); j < ( ( i + 1 ) * ( i + 1 ) - 1 ); j++ )
370 : {
371 47620 : set_val_Word32( sba_data[j], 0, input_frame );
372 : }
373 : }
374 :
375 20500 : return;
376 : }
|