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 "ivas_prot_rend.h"
37 : #include "ivas_rom_rend.h"
38 : #include "prot.h"
39 : #include "wmc_auto.h"
40 :
41 :
42 : /*---------------------------------------------------------------------*
43 : * Local function prototypes
44 : *---------------------------------------------------------------------*/
45 :
46 : static void sincResample( const float *input, float *output, const int16_t length_in, const int16_t length_out );
47 :
48 :
49 : /*---------------------------------------------------------------------*
50 : * TDREND_Apply_ITD()
51 : *
52 : * Apply ITD by delaying late channel
53 : *---------------------------------------------------------------------*/
54 :
55 3461327 : void TDREND_Apply_ITD(
56 : float *input, /* i : Input subframe to be time adjusted */
57 : float *out_left, /* o : Output left channel with ITD applied */
58 : float *out_right, /* o : Output right channel with ITD applied */
59 : int16_t *previtd, /* i/o: Previous ITD value */
60 : const int16_t itd, /* i : Current subframe ITD value */
61 : float *mem_itd, /* i/o: ITD buffer memory */
62 : const int16_t length /* i : Subframe length */
63 : )
64 : {
65 : int16_t transition_len;
66 : int16_t tlen1, tlen2, tlen3;
67 : int16_t length_in1;
68 : int16_t length_in2;
69 : int16_t currShift;
70 : int16_t prevShift;
71 : float *pstart1;
72 : float *pstart2;
73 : float *pstart3;
74 : float buffer[ITD_MEM_LEN + L_SUBFRAME5MS_48k];
75 : float *p_input;
76 : float *out_buf_A, *out_buf_B;
77 :
78 3461327 : push_wmops( "TDREND_Apply_ITD" );
79 :
80 : /* Prepare resampling buffer */
81 3461327 : mvr2r( mem_itd, buffer, ITD_MEM_LEN ); /* Retrieve memory */
82 3461327 : p_input = buffer + ITD_MEM_LEN; /* pointer to the current subframe */
83 3461327 : mvr2r( input, p_input, length ); /* input current subframe */
84 3461327 : mvr2r( buffer + length, mem_itd, ITD_MEM_LEN ); /* update memory for next frame */
85 :
86 3461327 : currShift = (int16_t) abs( itd );
87 3461327 : prevShift = (int16_t) abs( *previtd );
88 3461327 : tlen3 = max( 0, SFX_SPAT_BIN_SINC_M - currShift ); /* Make sure there is enough look-ahead for the sinc resampling */
89 3461327 : transition_len = length - tlen3;
90 :
91 3461327 : if ( ( ( *previtd ) * itd ) < 0 )
92 : {
93 : /* ITD sign change - apply shift on both channels */
94 99684 : tlen1 = (int16_t) ( ( (float) ( transition_len * prevShift ) / ( (float) ( prevShift + currShift ) ) ) + 0.5f );
95 99684 : tlen2 = transition_len - tlen1;
96 99684 : pstart1 = p_input - prevShift;
97 99684 : length_in1 = tlen1 + prevShift;
98 99684 : pstart2 = pstart1 + length_in1;
99 99684 : length_in2 = tlen2 - currShift;
100 99684 : pstart3 = pstart2 + length_in2;
101 : }
102 : else
103 : {
104 : /* ITD sign stays the same, or one of them is zero */
105 3361643 : tlen1 = transition_len;
106 3361643 : tlen2 = 0;
107 3361643 : pstart1 = p_input - prevShift;
108 3361643 : length_in1 = transition_len + prevShift - currShift;
109 3361643 : pstart2 = pstart1 + length_in1;
110 3361643 : length_in2 = 0;
111 3361643 : pstart3 = pstart2 + length_in2 + currShift;
112 : }
113 :
114 3461327 : if ( *previtd == 0 )
115 : {
116 307848 : if ( itd > 0 )
117 : {
118 12031 : out_buf_A = out_right;
119 12031 : out_buf_B = out_left;
120 : }
121 : else
122 : {
123 295817 : out_buf_A = out_left;
124 295817 : out_buf_B = out_right;
125 : }
126 : }
127 : else
128 : {
129 3153479 : if ( *previtd > 0 )
130 : {
131 1585921 : out_buf_A = out_right;
132 1585921 : out_buf_B = out_left;
133 : }
134 : else
135 : {
136 1567558 : out_buf_A = out_left;
137 1567558 : out_buf_B = out_right;
138 : }
139 : }
140 :
141 : /* Output buffer A */
142 3461327 : sincResample( pstart1, out_buf_A, length_in1, tlen1 );
143 3461327 : mvr2r( pstart2, out_buf_A + tlen1, length - tlen1 );
144 :
145 : /* Output buffer B */
146 3461327 : mvr2r( p_input, out_buf_B, tlen1 );
147 3461327 : sincResample( pstart2, out_buf_B + tlen1, length_in2, tlen2 );
148 3461327 : mvr2r( pstart3, out_buf_B + transition_len, tlen3 );
149 :
150 3461327 : *previtd = itd;
151 3461327 : pop_wmops();
152 3461327 : return;
153 : }
154 :
155 : /*---------------------------------------------------------------------*
156 : * sincResample()
157 : *
158 : * Resample signal (stretch/compress) to new ITD
159 : * The sinc resampling reads SFX_SPAT_BIN_SINC_M (5) samples outside of
160 : * the target frame.
161 : *---------------------------------------------------------------------*/
162 :
163 6922654 : static void sincResample(
164 : const float *input, /*i : Input signal */
165 : float *output, /*o : Output signal */
166 : const int16_t length_in, /*i : Input length */
167 : const int16_t length_out /*i : Output length */
168 : )
169 : {
170 : int16_t snc0;
171 : int16_t i, j;
172 : int16_t t;
173 : float t_frac;
174 : float t_step;
175 : float tmp;
176 : const float *p_mid;
177 : const float *p_forward;
178 : const float *p_backward;
179 : const float *p_sinc_forward;
180 : const float *p_sinc_backward;
181 :
182 : /* avoid division by 0 */
183 6922654 : if ( 0 == length_out )
184 : {
185 3361643 : return;
186 : }
187 :
188 : /* Compute fractional time step */
189 3561011 : t_step = (float) ( length_in ) / (float) ( length_out );
190 3561011 : t_frac = 0;
191 :
192 811929352 : for ( i = 0; i < length_out; i++ )
193 : {
194 808368341 : t = (int16_t) ( t_frac + EPSILON );
195 :
196 : /* Calculate the sinc-index for the center value of the sinc */
197 808368341 : snc0 = (int16_t) ( ( t_frac - t + EPSILON ) * SFX_SPAT_BIN_NUM_SUBSAMPLES + 0.5f );
198 :
199 : /* Run convolution forward and backward from mid point */
200 808368341 : p_mid = input + t;
201 808368341 : p_forward = p_mid + 1;
202 808368341 : p_backward = p_mid - 1;
203 808368341 : p_sinc_forward = SincTable + SFX_SPAT_BIN_NUM_SUBSAMPLES - snc0;
204 808368341 : p_sinc_backward = SincTable + SFX_SPAT_BIN_NUM_SUBSAMPLES + snc0;
205 :
206 808368341 : tmp = *p_mid * SincTable[snc0]; /* Middle point */
207 4041841705 : for ( j = 0; j < SFX_SPAT_BIN_SINC_M - 1; j++ )
208 : {
209 3233473364 : tmp += ( *p_forward ) * ( *p_sinc_forward ) + ( *p_backward ) * ( *p_sinc_backward );
210 3233473364 : p_sinc_forward += SFX_SPAT_BIN_NUM_SUBSAMPLES;
211 3233473364 : p_sinc_backward += SFX_SPAT_BIN_NUM_SUBSAMPLES;
212 3233473364 : p_forward++;
213 3233473364 : p_backward--;
214 : }
215 :
216 808368341 : output[i] = tmp;
217 :
218 : /* Advance fractional time */
219 808368341 : t_frac += t_step;
220 : }
221 :
222 3561011 : return;
223 : }
224 :
225 : /*-------------------------------------------------------------------*
226 : * TDREND_firfilt()
227 : *
228 : * FIR filtering function
229 : *
230 : --------------------------------------------------------------------*/
231 :
232 6922654 : void TDREND_firfilt(
233 : float *signal, /* i/o: Input signal / Filtered signal */
234 : float *filter, /* i/o: FIR filter */
235 : const float *filter_delta, /* i : FIR filter delta */
236 : const int16_t intp_count, /* i : interpolation count */
237 : float *mem, /* i/o: filter memory */
238 : const int16_t subframe_length, /* i : Length of signal */
239 : const int16_t filterlength, /* i : Filter length */
240 : const float Gain, /* i : Gain */
241 : const float prevGain /* i : Previous gain */
242 : )
243 : {
244 : float buffer[SFX_SPAT_BIN_MAX_FILTER_LENGTH - 1 + L_SUBFRAME5MS_48k];
245 : float *p_signal;
246 : float *p_tmp;
247 : float *p_filter;
248 : float tmp;
249 : int16_t i, j;
250 : float step, gain_tmp, gain_delta;
251 :
252 6922654 : gain_delta = ( Gain - prevGain );
253 6922654 : step = gain_delta / ( subframe_length );
254 6922654 : gain_tmp = prevGain;
255 :
256 : /* Handle memory */
257 6922654 : p_signal = buffer + filterlength - 1;
258 6922654 : mvr2r( mem, buffer, filterlength - 1 ); /* Insert memory */
259 6922654 : mvr2r( signal, p_signal, subframe_length ); /* Insert current frame */
260 6922654 : mvr2r( p_signal + subframe_length - filterlength + 1, mem, filterlength - 1 ); /* Update memory for next frame */
261 :
262 : /* Convolution */
263 1629685534 : for ( i = 0; i < subframe_length; i++ )
264 : {
265 1622762880 : tmp = 0.0f;
266 1622762880 : p_tmp = p_signal + i;
267 1622762880 : p_filter = filter;
268 >20684*10^7 : for ( j = 0; j < filterlength; j++ )
269 : {
270 >20522*10^7 : tmp += ( *p_filter++ ) * ( *p_tmp-- );
271 : }
272 : /* Apply linear gain interpolation in case of abrupt gain changes */
273 1622762880 : gain_tmp = gain_tmp + step;
274 1622762880 : signal[i] = tmp * gain_tmp;
275 :
276 1622762880 : if ( i < intp_count )
277 : {
278 42456554 : v_add( filter, filter_delta, filter, filterlength );
279 : }
280 : }
281 :
282 6922654 : return;
283 : }
|