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 <stdint.h>
34 : #include "options.h"
35 : #include <math.h>
36 : #include "cnst.h"
37 : #include "prot.h"
38 : #include "ivas_prot.h"
39 : #include "ivas_cnst.h"
40 : #include "ivas_rom_com.h"
41 : #include "ivas_rom_dec.h"
42 : #include "wmc_auto.h"
43 :
44 :
45 : /*-------------------------------------------------------------------------
46 : * Local constants
47 : *------------------------------------------------------------------------*/
48 :
49 : #define DOWNMIX_ALPHA 0.95f /* Smoothing coefficient */
50 : #define DOWNMIX_MAX_GAIN 4.0f /* Maximum allowed gain */
51 :
52 :
53 : /*-------------------------------------------------------------------------
54 : * ivas_mono_dmx_renderer_open()
55 : *
56 : * Open decoder downmix handle
57 : *-------------------------------------------------------------------------*/
58 :
59 141 : ivas_error ivas_mono_dmx_renderer_open(
60 : Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */
61 : )
62 : {
63 : MONO_DOWNMIX_RENDERER_HANDLE hDownmix;
64 :
65 141 : if ( ( hDownmix = (MONO_DOWNMIX_RENDERER_HANDLE) malloc( sizeof( MONO_DOWNMIX_RENDERER_STRUCT ) ) ) == NULL )
66 : {
67 0 : return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for downmixing\n" ) );
68 : }
69 :
70 141 : hDownmix->inputEnergy = 0;
71 141 : hDownmix->protoEnergy = 0;
72 141 : st_ivas->hMonoDmxRenderer = hDownmix;
73 :
74 141 : return IVAS_ERR_OK;
75 : }
76 :
77 :
78 : /*-------------------------------------------------------------------------
79 : * ivas_mono_dmx_renderer_close()
80 : *
81 : * Close decoder downmix handle
82 : *-------------------------------------------------------------------------*/
83 :
84 7758 : void ivas_mono_dmx_renderer_close(
85 : MONO_DOWNMIX_RENDERER_HANDLE *hMonoDmxRenderer /* i/ i/o: Mono downmix structure */
86 : )
87 : {
88 7758 : if ( hMonoDmxRenderer == NULL || *hMonoDmxRenderer == NULL )
89 : {
90 7617 : return;
91 : }
92 :
93 141 : free( *hMonoDmxRenderer );
94 141 : *hMonoDmxRenderer = NULL;
95 :
96 141 : return;
97 : }
98 :
99 :
100 : /*-------------------------------------------------------------------------
101 : * ivas_ism_mono_dmx()
102 : *
103 : * Downmix process
104 : *------------------------------------------------------------------------*/
105 :
106 17832 : void ivas_ism_mono_dmx(
107 : Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */
108 : float *output_f[], /* i/o: synthesized core-coder transport channels/mono output */
109 : const int16_t output_frame /* i : output frame length */
110 : )
111 : {
112 : int16_t i, j, numInputChannels;
113 : float proto_signal[L_FRAME48k], eq;
114 : float inputEnergy_local, protoEnergy_local;
115 : MONO_DOWNMIX_RENDERER_HANDLE hDownmix;
116 :
117 17832 : numInputChannels = st_ivas->nSCE;
118 17832 : if ( st_ivas->ivas_format == SBA_ISM_FORMAT )
119 : {
120 3000 : numInputChannels = st_ivas->nchan_ism;
121 : }
122 :
123 17832 : if ( st_ivas->ivas_format == MASA_ISM_FORMAT )
124 : {
125 2925 : if ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ )
126 : {
127 1785 : numInputChannels = st_ivas->nchan_transport + 1;
128 : }
129 : else
130 : {
131 1140 : numInputChannels = st_ivas->nchan_transport + st_ivas->nchan_ism;
132 : }
133 : }
134 :
135 17832 : hDownmix = st_ivas->hMonoDmxRenderer;
136 17832 : set_zero( proto_signal, output_frame );
137 17832 : inputEnergy_local = 0;
138 17832 : protoEnergy_local = 0;
139 :
140 : /* Compute the Proto Signal */
141 54291 : for ( i = 0; i < numInputChannels; i++ )
142 : {
143 36459 : v_add( output_f[i], proto_signal, proto_signal, output_frame );
144 : }
145 :
146 : /* compute the input energy, proto energy */
147 14285352 : for ( i = 0; i < output_frame; i++ )
148 : {
149 14267520 : protoEnergy_local += proto_signal[i] * proto_signal[i];
150 :
151 42576960 : for ( j = 0; j < numInputChannels; j++ )
152 : {
153 28309440 : inputEnergy_local += ( output_f[j][i] * output_f[j][i] );
154 : }
155 : }
156 17832 : hDownmix->inputEnergy *= DOWNMIX_ALPHA;
157 17832 : hDownmix->protoEnergy *= DOWNMIX_ALPHA;
158 17832 : hDownmix->inputEnergy += ( 1.0f - DOWNMIX_ALPHA ) * inputEnergy_local;
159 17832 : hDownmix->protoEnergy += ( 1.0f - DOWNMIX_ALPHA ) * protoEnergy_local;
160 :
161 : /* compute the eq factor */
162 17832 : eq = min( DOWNMIX_MAX_GAIN, sqrtf( hDownmix->inputEnergy / ( EPSILON + hDownmix->protoEnergy ) ) );
163 :
164 : /* equalize the downmix */
165 17832 : v_multc( proto_signal, eq, output_f[0], output_frame );
166 :
167 17832 : return;
168 : }
169 :
170 :
171 : /*-------------------------------------------------------------------------
172 : * ivas_mono_stereo_downmix_mcmasa()
173 : *
174 : * Downmix process in McMASA
175 : *------------------------------------------------------------------------*/
176 :
177 1497 : void ivas_mono_stereo_downmix_mcmasa(
178 : Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */
179 : float *output_f[], /* i/o: synthesized core-coder transport channels/mono or stereo output */
180 : int16_t output_frame /* i : output frame length per channel */
181 : )
182 : {
183 : int16_t i;
184 :
185 : float dmx_tmp[L_FRAME48k];
186 :
187 1497 : set_zero( dmx_tmp, output_frame );
188 :
189 : /* Dowmix center channel to L and R */
190 1497 : if ( st_ivas->hDecoderConfig->nchan_out == 2 && st_ivas->hOutSetup.separateChannelEnabled )
191 : {
192 600 : v_multc_acc( output_f[st_ivas->hOutSetup.separateChannelIndex], INV_SQRT2, output_f[0], output_frame );
193 600 : v_multc_acc( output_f[st_ivas->hOutSetup.separateChannelIndex], INV_SQRT2, output_f[1], output_frame );
194 : }
195 : /* Mono downmix */
196 897 : else if ( st_ivas->hDecoderConfig->nchan_out == 1 )
197 : {
198 : /* Downmix L and R to dmx_tmp */
199 2691 : for ( i = 0; i < st_ivas->nchan_transport; i++ )
200 : {
201 1794 : v_multc_acc( output_f[i], INV_SQRT2, dmx_tmp, output_frame );
202 : }
203 : /* Add center channel */
204 897 : if ( st_ivas->hOutSetup.separateChannelEnabled )
205 : {
206 447 : v_add( output_f[st_ivas->hOutSetup.separateChannelIndex], dmx_tmp, dmx_tmp, output_frame );
207 : }
208 :
209 : /* Move to output */
210 897 : mvr2r( dmx_tmp, output_f[0], output_frame );
211 : }
212 :
213 1497 : return;
214 : }
215 :
216 :
217 : /*-------------------------------------------------------------------------
218 : * ivas_apply_non_diegetic_panning()
219 : *
220 : * Apply non-diegetic panning
221 : *------------------------------------------------------------------------*/
222 :
223 10500 : void ivas_apply_non_diegetic_panning(
224 : float *input_f, /* i : non-diegetic object */
225 : float *output_f[], /* o : core-coder transport mono channel/stereo output */
226 : const float non_diegetic_pan_gain, /* i : non-diegetic panning gain */
227 : const int16_t output_frame /* i : output frame length per channel */
228 : )
229 : {
230 : float pan_left, pan_right;
231 :
232 10500 : pan_left = ( non_diegetic_pan_gain + 1.f ) * 0.5f;
233 10500 : pan_right = 1.f - pan_left;
234 10500 : v_multc( input_f, pan_right, output_f[1], output_frame );
235 10500 : v_multc( input_f, pan_left, output_f[0], output_frame );
236 :
237 10500 : return;
238 : }
|