Line data Source code
1 : /***********************************************************************
2 : Copyright (c) 2006-2011, Skype Limited. All rights reserved.
3 : Redistribution and use in source and binary forms, with or without
4 : modification, are permitted provided that the following conditions
5 : are met:
6 : - Redistributions of source code must retain the above copyright notice,
7 : this list of conditions and the following disclaimer.
8 : - Redistributions in binary form must reproduce the above copyright
9 : notice, this list of conditions and the following disclaimer in the
10 : documentation and/or other materials provided with the distribution.
11 : - Neither the name of Internet Society, IETF or IETF Trust, nor the
12 : names of specific contributors, may be used to endorse or promote
13 : products derived from this software without specific prior written
14 : permission.
15 : THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 : AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 : IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 : ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19 : LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 : CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 : SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 : INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 : CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 : ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 : POSSIBILITY OF SUCH DAMAGE.
26 : ***********************************************************************/
27 :
28 : #ifdef HAVE_CONFIG_H
29 : #include "config.h"
30 : #endif
31 :
32 : /*****************************************************************************
33 : * Pitch analyser function
34 : ******************************************************************************/
35 : #include "SigProc_FLP.h"
36 : #include "SigProc_FIX.h"
37 : #include "pitch_est_defines.h"
38 : #include "pitch.h"
39 :
40 : #define SCRATCH_SIZE 22
41 :
42 : /************************************************************/
43 : /* Internally used functions */
44 : /************************************************************/
45 : static void silk_P_Ana_calc_corr_st3(
46 : silk_float cross_corr_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ], /* O 3 DIM correlation array */
47 : const silk_float frame[], /* I vector to correlate */
48 : opus_int start_lag, /* I start lag */
49 : opus_int sf_length, /* I sub frame length */
50 : opus_int nb_subfr, /* I number of subframes */
51 : opus_int complexity, /* I Complexity setting */
52 : int arch /* I Run-time architecture */
53 : );
54 :
55 : static void silk_P_Ana_calc_energy_st3(
56 : silk_float energies_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ], /* O 3 DIM correlation array */
57 : const silk_float frame[], /* I vector to correlate */
58 : opus_int start_lag, /* I start lag */
59 : opus_int sf_length, /* I sub frame length */
60 : opus_int nb_subfr, /* I number of subframes */
61 : opus_int complexity /* I Complexity setting */
62 : );
63 :
64 : /************************************************************/
65 : /* CORE PITCH ANALYSIS FUNCTION */
66 : /************************************************************/
67 0 : opus_int silk_pitch_analysis_core_FLP( /* O Voicing estimate: 0 voiced, 1 unvoiced */
68 : const silk_float *frame, /* I Signal of length PE_FRAME_LENGTH_MS*Fs_kHz */
69 : opus_int *pitch_out, /* O Pitch lag values [nb_subfr] */
70 : opus_int16 *lagIndex, /* O Lag Index */
71 : opus_int8 *contourIndex, /* O Pitch contour Index */
72 : silk_float *LTPCorr, /* I/O Normalized correlation; input: value from previous frame */
73 : opus_int prevLag, /* I Last lag of previous frame; set to zero is unvoiced */
74 : const silk_float search_thres1, /* I First stage threshold for lag candidates 0 - 1 */
75 : const silk_float search_thres2, /* I Final threshold for lag candidates 0 - 1 */
76 : const opus_int Fs_kHz, /* I sample frequency (kHz) */
77 : const opus_int complexity, /* I Complexity setting, 0-2, where 2 is highest */
78 : const opus_int nb_subfr, /* I Number of 5 ms subframes */
79 : int arch /* I Run-time architecture */
80 : )
81 : {
82 : opus_int i, k, d, j;
83 : silk_float frame_8kHz[ PE_MAX_FRAME_LENGTH_MS * 8 ];
84 : silk_float frame_4kHz[ PE_MAX_FRAME_LENGTH_MS * 4 ];
85 : opus_int16 frame_8_FIX[ PE_MAX_FRAME_LENGTH_MS * 8 ];
86 : opus_int16 frame_4_FIX[ PE_MAX_FRAME_LENGTH_MS * 4 ];
87 : opus_int32 filt_state[ 6 ];
88 : silk_float threshold, contour_bias;
89 : silk_float C[ PE_MAX_NB_SUBFR][ (PE_MAX_LAG >> 1) + 5 ];
90 : opus_val32 xcorr[ PE_MAX_LAG_MS * 4 - PE_MIN_LAG_MS * 4 + 1 ];
91 : silk_float CC[ PE_NB_CBKS_STAGE2_EXT ];
92 : const silk_float *target_ptr, *basis_ptr;
93 : double cross_corr, normalizer, energy, energy_tmp;
94 : opus_int d_srch[ PE_D_SRCH_LENGTH ];
95 : opus_int16 d_comp[ (PE_MAX_LAG >> 1) + 5 ];
96 : opus_int length_d_srch, length_d_comp;
97 : silk_float Cmax, CCmax, CCmax_b, CCmax_new_b, CCmax_new;
98 : opus_int CBimax, CBimax_new, lag, start_lag, end_lag, lag_new;
99 : opus_int cbk_size;
100 : silk_float lag_log2, prevLag_log2, delta_lag_log2_sqr;
101 : silk_float energies_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ];
102 : silk_float cross_corr_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ];
103 : opus_int lag_counter;
104 : opus_int frame_length, frame_length_8kHz, frame_length_4kHz;
105 : opus_int sf_length, sf_length_8kHz, sf_length_4kHz;
106 : opus_int min_lag, min_lag_8kHz, min_lag_4kHz;
107 : opus_int max_lag, max_lag_8kHz, max_lag_4kHz;
108 : opus_int nb_cbk_search;
109 : const opus_int8 *Lag_CB_ptr;
110 :
111 : /* Check for valid sampling frequency */
112 0 : silk_assert( Fs_kHz == 8 || Fs_kHz == 12 || Fs_kHz == 16 );
113 :
114 : /* Check for valid complexity setting */
115 0 : silk_assert( complexity >= SILK_PE_MIN_COMPLEX );
116 0 : silk_assert( complexity <= SILK_PE_MAX_COMPLEX );
117 :
118 0 : silk_assert( search_thres1 >= 0.0f && search_thres1 <= 1.0f );
119 0 : silk_assert( search_thres2 >= 0.0f && search_thres2 <= 1.0f );
120 :
121 : /* Set up frame lengths max / min lag for the sampling frequency */
122 0 : frame_length = ( PE_LTP_MEM_LENGTH_MS + nb_subfr * PE_SUBFR_LENGTH_MS ) * Fs_kHz;
123 0 : frame_length_4kHz = ( PE_LTP_MEM_LENGTH_MS + nb_subfr * PE_SUBFR_LENGTH_MS ) * 4;
124 0 : frame_length_8kHz = ( PE_LTP_MEM_LENGTH_MS + nb_subfr * PE_SUBFR_LENGTH_MS ) * 8;
125 0 : sf_length = PE_SUBFR_LENGTH_MS * Fs_kHz;
126 0 : sf_length_4kHz = PE_SUBFR_LENGTH_MS * 4;
127 0 : sf_length_8kHz = PE_SUBFR_LENGTH_MS * 8;
128 0 : min_lag = PE_MIN_LAG_MS * Fs_kHz;
129 0 : min_lag_4kHz = PE_MIN_LAG_MS * 4;
130 0 : min_lag_8kHz = PE_MIN_LAG_MS * 8;
131 0 : max_lag = PE_MAX_LAG_MS * Fs_kHz - 1;
132 0 : max_lag_4kHz = PE_MAX_LAG_MS * 4;
133 0 : max_lag_8kHz = PE_MAX_LAG_MS * 8 - 1;
134 :
135 : /* Resample from input sampled at Fs_kHz to 8 kHz */
136 0 : if( Fs_kHz == 16 ) {
137 : /* Resample to 16 -> 8 khz */
138 : opus_int16 frame_16_FIX[ 16 * PE_MAX_FRAME_LENGTH_MS ];
139 0 : silk_float2short_array( frame_16_FIX, frame, frame_length );
140 0 : silk_memset( filt_state, 0, 2 * sizeof( opus_int32 ) );
141 0 : silk_resampler_down2( filt_state, frame_8_FIX, frame_16_FIX, frame_length );
142 0 : silk_short2float_array( frame_8kHz, frame_8_FIX, frame_length_8kHz );
143 0 : } else if( Fs_kHz == 12 ) {
144 : /* Resample to 12 -> 8 khz */
145 : opus_int16 frame_12_FIX[ 12 * PE_MAX_FRAME_LENGTH_MS ];
146 0 : silk_float2short_array( frame_12_FIX, frame, frame_length );
147 0 : silk_memset( filt_state, 0, 6 * sizeof( opus_int32 ) );
148 0 : silk_resampler_down2_3( filt_state, frame_8_FIX, frame_12_FIX, frame_length );
149 0 : silk_short2float_array( frame_8kHz, frame_8_FIX, frame_length_8kHz );
150 : } else {
151 0 : silk_assert( Fs_kHz == 8 );
152 0 : silk_float2short_array( frame_8_FIX, frame, frame_length_8kHz );
153 : }
154 :
155 : /* Decimate again to 4 kHz */
156 0 : silk_memset( filt_state, 0, 2 * sizeof( opus_int32 ) );
157 0 : silk_resampler_down2( filt_state, frame_4_FIX, frame_8_FIX, frame_length_8kHz );
158 0 : silk_short2float_array( frame_4kHz, frame_4_FIX, frame_length_4kHz );
159 :
160 : /* Low-pass filter */
161 0 : for( i = frame_length_4kHz - 1; i > 0; i-- ) {
162 0 : frame_4kHz[ i ] = silk_ADD_SAT16( frame_4kHz[ i ], frame_4kHz[ i - 1 ] );
163 : }
164 :
165 : /******************************************************************************
166 : * FIRST STAGE, operating in 4 khz
167 : ******************************************************************************/
168 0 : silk_memset(C, 0, sizeof(silk_float) * nb_subfr * ((PE_MAX_LAG >> 1) + 5));
169 0 : target_ptr = &frame_4kHz[ silk_LSHIFT( sf_length_4kHz, 2 ) ];
170 0 : for( k = 0; k < nb_subfr >> 1; k++ ) {
171 : /* Check that we are within range of the array */
172 0 : silk_assert( target_ptr >= frame_4kHz );
173 0 : silk_assert( target_ptr + sf_length_8kHz <= frame_4kHz + frame_length_4kHz );
174 :
175 0 : basis_ptr = target_ptr - min_lag_4kHz;
176 :
177 : /* Check that we are within range of the array */
178 0 : silk_assert( basis_ptr >= frame_4kHz );
179 0 : silk_assert( basis_ptr + sf_length_8kHz <= frame_4kHz + frame_length_4kHz );
180 :
181 0 : celt_pitch_xcorr( target_ptr, target_ptr-max_lag_4kHz, xcorr, sf_length_8kHz, max_lag_4kHz - min_lag_4kHz + 1, arch );
182 :
183 : /* Calculate first vector products before loop */
184 0 : cross_corr = xcorr[ max_lag_4kHz - min_lag_4kHz ];
185 0 : normalizer = silk_energy_FLP( target_ptr, sf_length_8kHz ) +
186 0 : silk_energy_FLP( basis_ptr, sf_length_8kHz ) +
187 0 : sf_length_8kHz * 4000.0f;
188 :
189 0 : C[ 0 ][ min_lag_4kHz ] += (silk_float)( 2 * cross_corr / normalizer );
190 :
191 : /* From now on normalizer is computed recursively */
192 0 : for( d = min_lag_4kHz + 1; d <= max_lag_4kHz; d++ ) {
193 0 : basis_ptr--;
194 :
195 : /* Check that we are within range of the array */
196 0 : silk_assert( basis_ptr >= frame_4kHz );
197 0 : silk_assert( basis_ptr + sf_length_8kHz <= frame_4kHz + frame_length_4kHz );
198 :
199 0 : cross_corr = xcorr[ max_lag_4kHz - d ];
200 :
201 : /* Add contribution of new sample and remove contribution from oldest sample */
202 0 : normalizer +=
203 0 : basis_ptr[ 0 ] * (double)basis_ptr[ 0 ] -
204 0 : basis_ptr[ sf_length_8kHz ] * (double)basis_ptr[ sf_length_8kHz ];
205 0 : C[ 0 ][ d ] += (silk_float)( 2 * cross_corr / normalizer );
206 : }
207 : /* Update target pointer */
208 0 : target_ptr += sf_length_8kHz;
209 : }
210 :
211 : /* Apply short-lag bias */
212 0 : for( i = max_lag_4kHz; i >= min_lag_4kHz; i-- ) {
213 0 : C[ 0 ][ i ] -= C[ 0 ][ i ] * i / 4096.0f;
214 : }
215 :
216 : /* Sort */
217 0 : length_d_srch = 4 + 2 * complexity;
218 0 : silk_assert( 3 * length_d_srch <= PE_D_SRCH_LENGTH );
219 0 : silk_insertion_sort_decreasing_FLP( &C[ 0 ][ min_lag_4kHz ], d_srch, max_lag_4kHz - min_lag_4kHz + 1, length_d_srch );
220 :
221 : /* Escape if correlation is very low already here */
222 0 : Cmax = C[ 0 ][ min_lag_4kHz ];
223 0 : if( Cmax < 0.2f ) {
224 0 : silk_memset( pitch_out, 0, nb_subfr * sizeof( opus_int ) );
225 0 : *LTPCorr = 0.0f;
226 0 : *lagIndex = 0;
227 0 : *contourIndex = 0;
228 0 : return 1;
229 : }
230 :
231 0 : threshold = search_thres1 * Cmax;
232 0 : for( i = 0; i < length_d_srch; i++ ) {
233 : /* Convert to 8 kHz indices for the sorted correlation that exceeds the threshold */
234 0 : if( C[ 0 ][ min_lag_4kHz + i ] > threshold ) {
235 0 : d_srch[ i ] = silk_LSHIFT( d_srch[ i ] + min_lag_4kHz, 1 );
236 : } else {
237 0 : length_d_srch = i;
238 0 : break;
239 : }
240 : }
241 0 : silk_assert( length_d_srch > 0 );
242 :
243 0 : for( i = min_lag_8kHz - 5; i < max_lag_8kHz + 5; i++ ) {
244 0 : d_comp[ i ] = 0;
245 : }
246 0 : for( i = 0; i < length_d_srch; i++ ) {
247 0 : d_comp[ d_srch[ i ] ] = 1;
248 : }
249 :
250 : /* Convolution */
251 0 : for( i = max_lag_8kHz + 3; i >= min_lag_8kHz; i-- ) {
252 0 : d_comp[ i ] += d_comp[ i - 1 ] + d_comp[ i - 2 ];
253 : }
254 :
255 0 : length_d_srch = 0;
256 0 : for( i = min_lag_8kHz; i < max_lag_8kHz + 1; i++ ) {
257 0 : if( d_comp[ i + 1 ] > 0 ) {
258 0 : d_srch[ length_d_srch ] = i;
259 0 : length_d_srch++;
260 : }
261 : }
262 :
263 : /* Convolution */
264 0 : for( i = max_lag_8kHz + 3; i >= min_lag_8kHz; i-- ) {
265 0 : d_comp[ i ] += d_comp[ i - 1 ] + d_comp[ i - 2 ] + d_comp[ i - 3 ];
266 : }
267 :
268 0 : length_d_comp = 0;
269 0 : for( i = min_lag_8kHz; i < max_lag_8kHz + 4; i++ ) {
270 0 : if( d_comp[ i ] > 0 ) {
271 0 : d_comp[ length_d_comp ] = (opus_int16)( i - 2 );
272 0 : length_d_comp++;
273 : }
274 : }
275 :
276 : /**********************************************************************************
277 : ** SECOND STAGE, operating at 8 kHz, on lag sections with high correlation
278 : *************************************************************************************/
279 : /*********************************************************************************
280 : * Find energy of each subframe projected onto its history, for a range of delays
281 : *********************************************************************************/
282 0 : silk_memset( C, 0, PE_MAX_NB_SUBFR*((PE_MAX_LAG >> 1) + 5) * sizeof(silk_float));
283 :
284 0 : if( Fs_kHz == 8 ) {
285 0 : target_ptr = &frame[ PE_LTP_MEM_LENGTH_MS * 8 ];
286 : } else {
287 0 : target_ptr = &frame_8kHz[ PE_LTP_MEM_LENGTH_MS * 8 ];
288 : }
289 0 : for( k = 0; k < nb_subfr; k++ ) {
290 0 : energy_tmp = silk_energy_FLP( target_ptr, sf_length_8kHz ) + 1.0;
291 0 : for( j = 0; j < length_d_comp; j++ ) {
292 0 : d = d_comp[ j ];
293 0 : basis_ptr = target_ptr - d;
294 0 : cross_corr = silk_inner_product_FLP( basis_ptr, target_ptr, sf_length_8kHz );
295 0 : if( cross_corr > 0.0f ) {
296 0 : energy = silk_energy_FLP( basis_ptr, sf_length_8kHz );
297 0 : C[ k ][ d ] = (silk_float)( 2 * cross_corr / ( energy + energy_tmp ) );
298 : } else {
299 0 : C[ k ][ d ] = 0.0f;
300 : }
301 : }
302 0 : target_ptr += sf_length_8kHz;
303 : }
304 :
305 : /* search over lag range and lags codebook */
306 : /* scale factor for lag codebook, as a function of center lag */
307 :
308 0 : CCmax = 0.0f; /* This value doesn't matter */
309 0 : CCmax_b = -1000.0f;
310 :
311 0 : CBimax = 0; /* To avoid returning undefined lag values */
312 0 : lag = -1; /* To check if lag with strong enough correlation has been found */
313 :
314 0 : if( prevLag > 0 ) {
315 0 : if( Fs_kHz == 12 ) {
316 0 : prevLag = silk_LSHIFT( prevLag, 1 ) / 3;
317 0 : } else if( Fs_kHz == 16 ) {
318 0 : prevLag = silk_RSHIFT( prevLag, 1 );
319 : }
320 0 : prevLag_log2 = silk_log2( (silk_float)prevLag );
321 : } else {
322 0 : prevLag_log2 = 0;
323 : }
324 :
325 : /* Set up stage 2 codebook based on number of subframes */
326 0 : if( nb_subfr == PE_MAX_NB_SUBFR ) {
327 0 : cbk_size = PE_NB_CBKS_STAGE2_EXT;
328 0 : Lag_CB_ptr = &silk_CB_lags_stage2[ 0 ][ 0 ];
329 0 : if( Fs_kHz == 8 && complexity > SILK_PE_MIN_COMPLEX ) {
330 : /* If input is 8 khz use a larger codebook here because it is last stage */
331 0 : nb_cbk_search = PE_NB_CBKS_STAGE2_EXT;
332 : } else {
333 0 : nb_cbk_search = PE_NB_CBKS_STAGE2;
334 : }
335 : } else {
336 0 : cbk_size = PE_NB_CBKS_STAGE2_10MS;
337 0 : Lag_CB_ptr = &silk_CB_lags_stage2_10_ms[ 0 ][ 0 ];
338 0 : nb_cbk_search = PE_NB_CBKS_STAGE2_10MS;
339 : }
340 :
341 0 : for( k = 0; k < length_d_srch; k++ ) {
342 0 : d = d_srch[ k ];
343 0 : for( j = 0; j < nb_cbk_search; j++ ) {
344 0 : CC[j] = 0.0f;
345 0 : for( i = 0; i < nb_subfr; i++ ) {
346 : /* Try all codebooks */
347 0 : CC[ j ] += C[ i ][ d + matrix_ptr( Lag_CB_ptr, i, j, cbk_size )];
348 : }
349 : }
350 : /* Find best codebook */
351 0 : CCmax_new = -1000.0f;
352 0 : CBimax_new = 0;
353 0 : for( i = 0; i < nb_cbk_search; i++ ) {
354 0 : if( CC[ i ] > CCmax_new ) {
355 0 : CCmax_new = CC[ i ];
356 0 : CBimax_new = i;
357 : }
358 : }
359 :
360 : /* Bias towards shorter lags */
361 0 : lag_log2 = silk_log2( (silk_float)d );
362 0 : CCmax_new_b = CCmax_new - PE_SHORTLAG_BIAS * nb_subfr * lag_log2;
363 :
364 : /* Bias towards previous lag */
365 0 : if( prevLag > 0 ) {
366 0 : delta_lag_log2_sqr = lag_log2 - prevLag_log2;
367 0 : delta_lag_log2_sqr *= delta_lag_log2_sqr;
368 0 : CCmax_new_b -= PE_PREVLAG_BIAS * nb_subfr * (*LTPCorr) * delta_lag_log2_sqr / ( delta_lag_log2_sqr + 0.5f );
369 : }
370 :
371 0 : if( CCmax_new_b > CCmax_b && /* Find maximum biased correlation */
372 0 : CCmax_new > nb_subfr * search_thres2 /* Correlation needs to be high enough to be voiced */
373 : ) {
374 0 : CCmax_b = CCmax_new_b;
375 0 : CCmax = CCmax_new;
376 0 : lag = d;
377 0 : CBimax = CBimax_new;
378 : }
379 : }
380 :
381 0 : if( lag == -1 ) {
382 : /* No suitable candidate found */
383 0 : silk_memset( pitch_out, 0, PE_MAX_NB_SUBFR * sizeof(opus_int) );
384 0 : *LTPCorr = 0.0f;
385 0 : *lagIndex = 0;
386 0 : *contourIndex = 0;
387 0 : return 1;
388 : }
389 :
390 : /* Output normalized correlation */
391 0 : *LTPCorr = (silk_float)( CCmax / nb_subfr );
392 0 : silk_assert( *LTPCorr >= 0.0f );
393 :
394 0 : if( Fs_kHz > 8 ) {
395 : /* Search in original signal */
396 :
397 : /* Compensate for decimation */
398 0 : silk_assert( lag == silk_SAT16( lag ) );
399 0 : if( Fs_kHz == 12 ) {
400 0 : lag = silk_RSHIFT_ROUND( silk_SMULBB( lag, 3 ), 1 );
401 : } else { /* Fs_kHz == 16 */
402 0 : lag = silk_LSHIFT( lag, 1 );
403 : }
404 :
405 0 : lag = silk_LIMIT_int( lag, min_lag, max_lag );
406 0 : start_lag = silk_max_int( lag - 2, min_lag );
407 0 : end_lag = silk_min_int( lag + 2, max_lag );
408 0 : lag_new = lag; /* to avoid undefined lag */
409 0 : CBimax = 0; /* to avoid undefined lag */
410 :
411 0 : CCmax = -1000.0f;
412 :
413 : /* Calculate the correlations and energies needed in stage 3 */
414 0 : silk_P_Ana_calc_corr_st3( cross_corr_st3, frame, start_lag, sf_length, nb_subfr, complexity, arch );
415 0 : silk_P_Ana_calc_energy_st3( energies_st3, frame, start_lag, sf_length, nb_subfr, complexity );
416 :
417 0 : lag_counter = 0;
418 0 : silk_assert( lag == silk_SAT16( lag ) );
419 0 : contour_bias = PE_FLATCONTOUR_BIAS / lag;
420 :
421 : /* Set up cbk parameters according to complexity setting and frame length */
422 0 : if( nb_subfr == PE_MAX_NB_SUBFR ) {
423 0 : nb_cbk_search = (opus_int)silk_nb_cbk_searchs_stage3[ complexity ];
424 0 : cbk_size = PE_NB_CBKS_STAGE3_MAX;
425 0 : Lag_CB_ptr = &silk_CB_lags_stage3[ 0 ][ 0 ];
426 : } else {
427 0 : nb_cbk_search = PE_NB_CBKS_STAGE3_10MS;
428 0 : cbk_size = PE_NB_CBKS_STAGE3_10MS;
429 0 : Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ];
430 : }
431 :
432 0 : target_ptr = &frame[ PE_LTP_MEM_LENGTH_MS * Fs_kHz ];
433 0 : energy_tmp = silk_energy_FLP( target_ptr, nb_subfr * sf_length ) + 1.0;
434 0 : for( d = start_lag; d <= end_lag; d++ ) {
435 0 : for( j = 0; j < nb_cbk_search; j++ ) {
436 0 : cross_corr = 0.0;
437 0 : energy = energy_tmp;
438 0 : for( k = 0; k < nb_subfr; k++ ) {
439 0 : cross_corr += cross_corr_st3[ k ][ j ][ lag_counter ];
440 0 : energy += energies_st3[ k ][ j ][ lag_counter ];
441 : }
442 0 : if( cross_corr > 0.0 ) {
443 0 : CCmax_new = (silk_float)( 2 * cross_corr / energy );
444 : /* Reduce depending on flatness of contour */
445 0 : CCmax_new *= 1.0f - contour_bias * j;
446 : } else {
447 0 : CCmax_new = 0.0f;
448 : }
449 :
450 0 : if( CCmax_new > CCmax && ( d + (opus_int)silk_CB_lags_stage3[ 0 ][ j ] ) <= max_lag ) {
451 0 : CCmax = CCmax_new;
452 0 : lag_new = d;
453 0 : CBimax = j;
454 : }
455 : }
456 0 : lag_counter++;
457 : }
458 :
459 0 : for( k = 0; k < nb_subfr; k++ ) {
460 0 : pitch_out[ k ] = lag_new + matrix_ptr( Lag_CB_ptr, k, CBimax, cbk_size );
461 0 : pitch_out[ k ] = silk_LIMIT( pitch_out[ k ], min_lag, PE_MAX_LAG_MS * Fs_kHz );
462 : }
463 0 : *lagIndex = (opus_int16)( lag_new - min_lag );
464 0 : *contourIndex = (opus_int8)CBimax;
465 : } else { /* Fs_kHz == 8 */
466 : /* Save Lags */
467 0 : for( k = 0; k < nb_subfr; k++ ) {
468 0 : pitch_out[ k ] = lag + matrix_ptr( Lag_CB_ptr, k, CBimax, cbk_size );
469 0 : pitch_out[ k ] = silk_LIMIT( pitch_out[ k ], min_lag_8kHz, PE_MAX_LAG_MS * 8 );
470 : }
471 0 : *lagIndex = (opus_int16)( lag - min_lag_8kHz );
472 0 : *contourIndex = (opus_int8)CBimax;
473 : }
474 0 : silk_assert( *lagIndex >= 0 );
475 : /* return as voiced */
476 0 : return 0;
477 : }
478 :
479 : /***********************************************************************
480 : * Calculates the correlations used in stage 3 search. In order to cover
481 : * the whole lag codebook for all the searched offset lags (lag +- 2),
482 : * the following correlations are needed in each sub frame:
483 : *
484 : * sf1: lag range [-8,...,7] total 16 correlations
485 : * sf2: lag range [-4,...,4] total 9 correlations
486 : * sf3: lag range [-3,....4] total 8 correltions
487 : * sf4: lag range [-6,....8] total 15 correlations
488 : *
489 : * In total 48 correlations. The direct implementation computed in worst
490 : * case 4*12*5 = 240 correlations, but more likely around 120.
491 : ***********************************************************************/
492 0 : static void silk_P_Ana_calc_corr_st3(
493 : silk_float cross_corr_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ], /* O 3 DIM correlation array */
494 : const silk_float frame[], /* I vector to correlate */
495 : opus_int start_lag, /* I start lag */
496 : opus_int sf_length, /* I sub frame length */
497 : opus_int nb_subfr, /* I number of subframes */
498 : opus_int complexity, /* I Complexity setting */
499 : int arch /* I Run-time architecture */
500 : )
501 : {
502 : const silk_float *target_ptr;
503 : opus_int i, j, k, lag_counter, lag_low, lag_high;
504 : opus_int nb_cbk_search, delta, idx, cbk_size;
505 : silk_float scratch_mem[ SCRATCH_SIZE ];
506 : opus_val32 xcorr[ SCRATCH_SIZE ];
507 : const opus_int8 *Lag_range_ptr, *Lag_CB_ptr;
508 :
509 0 : silk_assert( complexity >= SILK_PE_MIN_COMPLEX );
510 0 : silk_assert( complexity <= SILK_PE_MAX_COMPLEX );
511 :
512 0 : if( nb_subfr == PE_MAX_NB_SUBFR ) {
513 0 : Lag_range_ptr = &silk_Lag_range_stage3[ complexity ][ 0 ][ 0 ];
514 0 : Lag_CB_ptr = &silk_CB_lags_stage3[ 0 ][ 0 ];
515 0 : nb_cbk_search = silk_nb_cbk_searchs_stage3[ complexity ];
516 0 : cbk_size = PE_NB_CBKS_STAGE3_MAX;
517 : } else {
518 0 : silk_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1);
519 0 : Lag_range_ptr = &silk_Lag_range_stage3_10_ms[ 0 ][ 0 ];
520 0 : Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ];
521 0 : nb_cbk_search = PE_NB_CBKS_STAGE3_10MS;
522 0 : cbk_size = PE_NB_CBKS_STAGE3_10MS;
523 : }
524 :
525 0 : target_ptr = &frame[ silk_LSHIFT( sf_length, 2 ) ]; /* Pointer to middle of frame */
526 0 : for( k = 0; k < nb_subfr; k++ ) {
527 0 : lag_counter = 0;
528 :
529 : /* Calculate the correlations for each subframe */
530 0 : lag_low = matrix_ptr( Lag_range_ptr, k, 0, 2 );
531 0 : lag_high = matrix_ptr( Lag_range_ptr, k, 1, 2 );
532 0 : silk_assert(lag_high-lag_low+1 <= SCRATCH_SIZE);
533 0 : celt_pitch_xcorr( target_ptr, target_ptr - start_lag - lag_high, xcorr, sf_length, lag_high - lag_low + 1, arch );
534 0 : for( j = lag_low; j <= lag_high; j++ ) {
535 0 : silk_assert( lag_counter < SCRATCH_SIZE );
536 0 : scratch_mem[ lag_counter ] = xcorr[ lag_high - j ];
537 0 : lag_counter++;
538 : }
539 :
540 0 : delta = matrix_ptr( Lag_range_ptr, k, 0, 2 );
541 0 : for( i = 0; i < nb_cbk_search; i++ ) {
542 : /* Fill out the 3 dim array that stores the correlations for */
543 : /* each code_book vector for each start lag */
544 0 : idx = matrix_ptr( Lag_CB_ptr, k, i, cbk_size ) - delta;
545 0 : for( j = 0; j < PE_NB_STAGE3_LAGS; j++ ) {
546 0 : silk_assert( idx + j < SCRATCH_SIZE );
547 0 : silk_assert( idx + j < lag_counter );
548 0 : cross_corr_st3[ k ][ i ][ j ] = scratch_mem[ idx + j ];
549 : }
550 : }
551 0 : target_ptr += sf_length;
552 : }
553 0 : }
554 :
555 : /********************************************************************/
556 : /* Calculate the energies for first two subframes. The energies are */
557 : /* calculated recursively. */
558 : /********************************************************************/
559 0 : static void silk_P_Ana_calc_energy_st3(
560 : silk_float energies_st3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ][ PE_NB_STAGE3_LAGS ], /* O 3 DIM correlation array */
561 : const silk_float frame[], /* I vector to correlate */
562 : opus_int start_lag, /* I start lag */
563 : opus_int sf_length, /* I sub frame length */
564 : opus_int nb_subfr, /* I number of subframes */
565 : opus_int complexity /* I Complexity setting */
566 : )
567 : {
568 : const silk_float *target_ptr, *basis_ptr;
569 : double energy;
570 : opus_int k, i, j, lag_counter;
571 : opus_int nb_cbk_search, delta, idx, cbk_size, lag_diff;
572 : silk_float scratch_mem[ SCRATCH_SIZE ];
573 : const opus_int8 *Lag_range_ptr, *Lag_CB_ptr;
574 :
575 0 : silk_assert( complexity >= SILK_PE_MIN_COMPLEX );
576 0 : silk_assert( complexity <= SILK_PE_MAX_COMPLEX );
577 :
578 0 : if( nb_subfr == PE_MAX_NB_SUBFR ) {
579 0 : Lag_range_ptr = &silk_Lag_range_stage3[ complexity ][ 0 ][ 0 ];
580 0 : Lag_CB_ptr = &silk_CB_lags_stage3[ 0 ][ 0 ];
581 0 : nb_cbk_search = silk_nb_cbk_searchs_stage3[ complexity ];
582 0 : cbk_size = PE_NB_CBKS_STAGE3_MAX;
583 : } else {
584 0 : silk_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1);
585 0 : Lag_range_ptr = &silk_Lag_range_stage3_10_ms[ 0 ][ 0 ];
586 0 : Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ];
587 0 : nb_cbk_search = PE_NB_CBKS_STAGE3_10MS;
588 0 : cbk_size = PE_NB_CBKS_STAGE3_10MS;
589 : }
590 :
591 0 : target_ptr = &frame[ silk_LSHIFT( sf_length, 2 ) ];
592 0 : for( k = 0; k < nb_subfr; k++ ) {
593 0 : lag_counter = 0;
594 :
595 : /* Calculate the energy for first lag */
596 0 : basis_ptr = target_ptr - ( start_lag + matrix_ptr( Lag_range_ptr, k, 0, 2 ) );
597 0 : energy = silk_energy_FLP( basis_ptr, sf_length ) + 1e-3;
598 0 : silk_assert( energy >= 0.0 );
599 0 : scratch_mem[lag_counter] = (silk_float)energy;
600 0 : lag_counter++;
601 :
602 0 : lag_diff = ( matrix_ptr( Lag_range_ptr, k, 1, 2 ) - matrix_ptr( Lag_range_ptr, k, 0, 2 ) + 1 );
603 0 : for( i = 1; i < lag_diff; i++ ) {
604 : /* remove part outside new window */
605 0 : energy -= basis_ptr[sf_length - i] * (double)basis_ptr[sf_length - i];
606 0 : silk_assert( energy >= 0.0 );
607 :
608 : /* add part that comes into window */
609 0 : energy += basis_ptr[ -i ] * (double)basis_ptr[ -i ];
610 0 : silk_assert( energy >= 0.0 );
611 0 : silk_assert( lag_counter < SCRATCH_SIZE );
612 0 : scratch_mem[lag_counter] = (silk_float)energy;
613 0 : lag_counter++;
614 : }
615 :
616 0 : delta = matrix_ptr( Lag_range_ptr, k, 0, 2 );
617 0 : for( i = 0; i < nb_cbk_search; i++ ) {
618 : /* Fill out the 3 dim array that stores the correlations for */
619 : /* each code_book vector for each start lag */
620 0 : idx = matrix_ptr( Lag_CB_ptr, k, i, cbk_size ) - delta;
621 0 : for( j = 0; j < PE_NB_STAGE3_LAGS; j++ ) {
622 0 : silk_assert( idx + j < SCRATCH_SIZE );
623 0 : silk_assert( idx + j < lag_counter );
624 0 : energies_st3[ k ][ i ][ j ] = scratch_mem[ idx + j ];
625 0 : silk_assert( energies_st3[ k ][ i ][ j ] >= 0.0f );
626 : }
627 : }
628 0 : target_ptr += sf_length;
629 : }
630 0 : }
|