1 /* |
|
2 * Copyright (c) 2010 Ixonos Plc. |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - Initial contribution |
|
11 * |
|
12 * Contributors: |
|
13 * Ixonos Plc |
|
14 * |
|
15 * Description: |
|
16 * |
|
17 */ |
|
18 |
|
19 |
|
20 /* |
|
21 \file |
|
22 \brief Frequency scale calculation $Revision: 1.2.4.1 $ |
|
23 */ |
|
24 |
|
25 /************************************************************************** |
|
26 sbr_freq_sca.cpp - SBR frequency scale calculations. |
|
27 |
|
28 Author(s): Juha Ojanpera |
|
29 Copyright (c) 2004 by Nokia Research Center, Multimedia Technologies. |
|
30 *************************************************************************/ |
|
31 |
|
32 /*-- System Headers. --*/ |
|
33 #include <e32math.h> |
|
34 |
|
35 /*-- Project Headers. --*/ |
|
36 #include "sbr_rom.h" |
|
37 |
|
38 const int16 MAX_OCTAVE = 29; |
|
39 const int16 MAX_SECOND_REGION = 50; |
|
40 const FLOAT WARP_FACTOR = 25200.0f / 32768.0f; |
|
41 |
|
42 /*! |
|
43 \brief Sorting routine |
|
44 */ |
|
45 void |
|
46 shellsort(uint8 *in, uint8 n) |
|
47 { |
|
48 int16 i, j, v, w, inc = 1; |
|
49 |
|
50 do |
|
51 { |
|
52 inc = 3 * inc + 1; |
|
53 |
|
54 } while (inc <= n); |
|
55 |
|
56 do |
|
57 { |
|
58 inc = inc / 3; |
|
59 |
|
60 for(i = inc; i < n; i++) |
|
61 { |
|
62 v = in[i]; |
|
63 j = i; |
|
64 |
|
65 while((w = in[j - inc]) > v) |
|
66 { |
|
67 in[j] = w; |
|
68 j -= inc; |
|
69 if(j < inc) |
|
70 break; |
|
71 } |
|
72 in[j] = v; |
|
73 } |
|
74 |
|
75 } while(inc > 1); |
|
76 } |
|
77 |
|
78 /*! |
|
79 \brief Calculate number of SBR bands between start and stop band |
|
80 |
|
81 \return number of bands |
|
82 */ |
|
83 static int16 |
|
84 numberOfBands(FLOAT bpo, int16 start, int16 stop, int16 warpFlag) |
|
85 { |
|
86 int16 num_bands; |
|
87 FLOAT num_bands_div2; |
|
88 |
|
89 num_bands_div2 = 0.5f * FloatFR_getNumOctaves(start, stop) * bpo; |
|
90 if(warpFlag) num_bands_div2 *= WARP_FACTOR; |
|
91 |
|
92 num_bands_div2 += 0.5f; |
|
93 num_bands = (int16) num_bands_div2; |
|
94 num_bands <<= 1; |
|
95 |
|
96 return (num_bands); |
|
97 } |
|
98 |
|
99 /*! |
|
100 \brief Calculate width of SBR bands |
|
101 |
|
102 */ |
|
103 static void |
|
104 CalcBands(uint8 *diff, uint8 start, uint8 stop, uint8 num_bands) |
|
105 { |
|
106 FLOAT exact, bandfactor; |
|
107 int16 i, previous, current; |
|
108 |
|
109 previous = start; |
|
110 exact = (FLOAT) start; |
|
111 |
|
112 Math::Pow(bandfactor, stop * sbr_invIntTable[start], sbr_invIntTable[num_bands]); |
|
113 |
|
114 for(i = 1; i <= num_bands; i++) |
|
115 { |
|
116 exact *= bandfactor; |
|
117 current = (int16) (exact + 0.5f); |
|
118 diff[i - 1] = current - previous; |
|
119 previous = current; |
|
120 } |
|
121 } |
|
122 |
|
123 /*! |
|
124 \brief Calculate cumulated sum vector from delta vector |
|
125 */ |
|
126 static void |
|
127 cumSum(uint8 start_value, uint8* diff, uint8 length, uint8 *start_adress) |
|
128 { |
|
129 int16 i; |
|
130 |
|
131 start_adress[0] = start_value; |
|
132 for(i = 1; i <= length; i++) |
|
133 start_adress[i] = start_adress[i - 1] + diff[i - 1]; |
|
134 } |
|
135 |
|
136 /*! |
|
137 \brief Adapt width of frequency bands in the second region |
|
138 */ |
|
139 static int16 |
|
140 modifyBands(uint8 max_band_previous, uint8 * diff, uint8 length) |
|
141 { |
|
142 int16 change = max_band_previous - diff[0]; |
|
143 |
|
144 if(change > (diff[length - 1] - diff[0]) / 2) |
|
145 change = (diff[length - 1] - diff[0]) / 2; |
|
146 |
|
147 diff[0] += change; |
|
148 diff[length - 1] -= change; |
|
149 shellsort(diff, length); |
|
150 |
|
151 return (0); |
|
152 } |
|
153 |
|
154 /*! |
|
155 \brief Retrieve QMF-band where the SBR range starts |
|
156 |
|
157 \return Number of start band |
|
158 */ |
|
159 static int16 |
|
160 getStartBand(int32 fs, uint8 startFreq) |
|
161 { |
|
162 int16 band; |
|
163 |
|
164 switch(fs) |
|
165 { |
|
166 case 96000: |
|
167 case 88200: |
|
168 band = sbr_start_freq_88[startFreq]; |
|
169 break; |
|
170 |
|
171 case 64000: |
|
172 band = sbr_start_freq_64[startFreq]; |
|
173 break; |
|
174 |
|
175 case 48000: |
|
176 band = sbr_start_freq_48[startFreq]; |
|
177 break; |
|
178 |
|
179 case 44100: |
|
180 band = sbr_start_freq_44[startFreq]; |
|
181 break; |
|
182 |
|
183 case 32000: |
|
184 band = sbr_start_freq_32[startFreq]; |
|
185 break; |
|
186 |
|
187 case 24000: |
|
188 band = sbr_start_freq_24[startFreq]; |
|
189 break; |
|
190 |
|
191 case 22050: |
|
192 band = sbr_start_freq_22[startFreq]; |
|
193 break; |
|
194 |
|
195 case 16000: |
|
196 band = sbr_start_freq_16[startFreq]; |
|
197 break; |
|
198 |
|
199 default: |
|
200 band = -1; |
|
201 break; |
|
202 } |
|
203 |
|
204 return (band); |
|
205 } |
|
206 |
|
207 /*! |
|
208 \brief Generates master frequency tables |
|
209 |
|
210 \return errorCode, 0 if successful |
|
211 */ |
|
212 int16 |
|
213 sbrdecUpdateFreqScale(uint8 * v_k_master, uint8 *numMaster, SbrHeaderData *hHeaderData) |
|
214 { |
|
215 int32 fs; |
|
216 FLOAT bpo; |
|
217 int16 err, dk, k2_achived, k2_diff, incr; |
|
218 uint8 k0, k2, k1, i, num_bands0, num_bands1; |
|
219 uint8 diff_tot[MAX_OCTAVE + MAX_SECOND_REGION], *diff0, *diff1; |
|
220 |
|
221 diff0 = diff_tot; |
|
222 diff1 = diff_tot + MAX_OCTAVE; |
|
223 |
|
224 incr = k1 = dk = err = 0; |
|
225 fs = hHeaderData->outSampleRate; |
|
226 |
|
227 k0 = getStartBand(fs, hHeaderData->startFreq); |
|
228 |
|
229 if(hHeaderData->stopFreq < 14) |
|
230 { |
|
231 switch(fs) |
|
232 { |
|
233 case 48000: |
|
234 k1 = 21; |
|
235 break; |
|
236 |
|
237 case 44100: |
|
238 k1 = 23; |
|
239 break; |
|
240 |
|
241 case 32000: |
|
242 case 24000: |
|
243 k1 = 32; |
|
244 break; |
|
245 |
|
246 case 22050: |
|
247 k1 = 35; |
|
248 break; |
|
249 |
|
250 case 16000: |
|
251 k1 = 48; |
|
252 break; |
|
253 |
|
254 default: |
|
255 return (1); |
|
256 } |
|
257 |
|
258 CalcBands(diff0, k1, 64, 13); |
|
259 shellsort(diff0, 13); |
|
260 cumSum(k1, diff0, 13, diff1); |
|
261 k2 = diff1[hHeaderData->stopFreq]; |
|
262 } |
|
263 else |
|
264 { |
|
265 if(hHeaderData->stopFreq == 14) |
|
266 k2 = 2 * k0; |
|
267 else |
|
268 k2 = 3 * k0; |
|
269 } |
|
270 |
|
271 if(k2 > NO_SYNTHESIS_CHANNELS) |
|
272 k2 = NO_SYNTHESIS_CHANNELS; |
|
273 |
|
274 if(((k2 - k0) > MAX_FREQ_COEFFS) || (k2 <= k0) ) |
|
275 return (2); |
|
276 |
|
277 if(fs == 44100 && ((k2 - k0) > MAX_FREQ_COEFFS_FS44100)) |
|
278 return (3); |
|
279 |
|
280 if(fs >= 48000 && ((k2 - k0) > MAX_FREQ_COEFFS_FS48000)) |
|
281 return (4); |
|
282 |
|
283 if(hHeaderData->freqScale>0) |
|
284 { |
|
285 if(hHeaderData->freqScale == 1) |
|
286 bpo = 12.0f; |
|
287 else |
|
288 { |
|
289 if(hHeaderData->freqScale == 2) |
|
290 bpo = 10.0f; |
|
291 else |
|
292 bpo = 8.0f; |
|
293 } |
|
294 |
|
295 if(1000 * k2 > 2245 * k0) |
|
296 { |
|
297 k1 = 2 * k0; |
|
298 num_bands0 = numberOfBands(bpo, k0, k1, 0); |
|
299 num_bands1 = numberOfBands(bpo, k1, k2, hHeaderData->alterScale); |
|
300 |
|
301 if(num_bands0 < 1) |
|
302 return (5); |
|
303 |
|
304 if(num_bands1 < 1) |
|
305 return (6); |
|
306 |
|
307 CalcBands(diff0, k0, k1, num_bands0); |
|
308 shellsort(diff0, num_bands0); |
|
309 |
|
310 if(diff0[0] == 0) |
|
311 return (7); |
|
312 |
|
313 cumSum(k0, diff0, num_bands0, v_k_master); |
|
314 CalcBands(diff1, k1, k2, num_bands1); |
|
315 shellsort(diff1, num_bands1); |
|
316 |
|
317 if(diff0[num_bands0-1] > diff1[0]) |
|
318 { |
|
319 err = modifyBands(diff0[num_bands0 - 1], diff1, num_bands1); |
|
320 if(err) return (8); |
|
321 } |
|
322 |
|
323 cumSum(k1, diff1, num_bands1, &v_k_master[num_bands0]); |
|
324 *numMaster = num_bands0 + num_bands1; |
|
325 } |
|
326 else |
|
327 { |
|
328 k1 = k2; |
|
329 |
|
330 num_bands0 = numberOfBands(bpo, k0, k1, 0); |
|
331 if(num_bands0 < 1) |
|
332 return (9); |
|
333 |
|
334 CalcBands(diff0, k0, k1, num_bands0); |
|
335 shellsort(diff0, num_bands0); |
|
336 if(diff0[0] == 0) |
|
337 return (10); |
|
338 |
|
339 cumSum(k0, diff0, num_bands0, v_k_master); |
|
340 *numMaster = num_bands0; |
|
341 } |
|
342 } |
|
343 else |
|
344 { |
|
345 if(hHeaderData->alterScale == 0) |
|
346 { |
|
347 dk = 1; |
|
348 num_bands0 = (k2 - k0) & 254; |
|
349 } |
|
350 else |
|
351 { |
|
352 dk = 2; |
|
353 num_bands0 = (((k2 - k0) >> 1) + 1) & 254; |
|
354 } |
|
355 |
|
356 if(num_bands0 < 1) |
|
357 return (11); |
|
358 |
|
359 k2_achived = k0 + num_bands0 * dk; |
|
360 k2_diff = k2 - k2_achived; |
|
361 |
|
362 for(i = 0;i < num_bands0; i++) |
|
363 diff_tot[i] = dk; |
|
364 |
|
365 if(k2_diff < 0) |
|
366 { |
|
367 incr = 1; |
|
368 i = 0; |
|
369 } |
|
370 |
|
371 if(k2_diff > 0) |
|
372 { |
|
373 incr = -1; |
|
374 i = num_bands0 - 1; |
|
375 } |
|
376 |
|
377 while(k2_diff != 0) |
|
378 { |
|
379 diff_tot[i] = diff_tot[i] - incr; |
|
380 i = i + incr; |
|
381 k2_diff = k2_diff + incr; |
|
382 } |
|
383 |
|
384 cumSum(k0, diff_tot, num_bands0, v_k_master); |
|
385 |
|
386 *numMaster = num_bands0; |
|
387 } |
|
388 |
|
389 if(*numMaster < 1) |
|
390 return (12); |
|
391 |
|
392 return (0); |
|
393 } |
|
394 |
|
395 /*! |
|
396 \brief Reset frequency band tables |
|
397 |
|
398 \return error code, 0 on success |
|
399 */ |
|
400 int16 |
|
401 resetFreqBandTables(SbrHeaderData *hHeaderData) |
|
402 { |
|
403 uint8 nBandsHi; |
|
404 int16 err, k2, kx, intTemp; |
|
405 FreqBandData *hFreq = hHeaderData->hFreqBandData; |
|
406 |
|
407 err = sbrdecUpdateFreqScale(hFreq->v_k_master, &hFreq->numMaster, hHeaderData); |
|
408 if(err) return (err); |
|
409 |
|
410 if(hHeaderData->xover_band > hFreq->numMaster) |
|
411 return (13); |
|
412 |
|
413 nBandsHi = hFreq->numMaster - hHeaderData->xover_band; |
|
414 |
|
415 hFreq->nSfb[0] = ((nBandsHi & 1) == 0) ? nBandsHi >> 1 : (nBandsHi + 1) >> 1; |
|
416 hFreq->nSfb[1] = nBandsHi; |
|
417 |
|
418 k2 = hFreq->v_k_master[nBandsHi - hHeaderData->xover_band]; |
|
419 kx = hFreq->v_k_master[hHeaderData->xover_band]; |
|
420 |
|
421 if(hHeaderData->noise_bands == 0) |
|
422 hFreq->nNfb = 1; |
|
423 else |
|
424 { |
|
425 FLOAT temp; |
|
426 |
|
427 temp = FloatFR_getNumOctaves(kx,k2); |
|
428 temp = temp * (FLOAT) hHeaderData->noise_bands; |
|
429 intTemp = (int16) (temp + 0.5f); |
|
430 |
|
431 if(intTemp == 0) |
|
432 intTemp = 1; |
|
433 |
|
434 hFreq->nNfb = intTemp; |
|
435 } |
|
436 |
|
437 hFreq->nInvfBands = hFreq->nNfb; |
|
438 |
|
439 if(hFreq->nNfb > MAX_NOISE_COEFFS) |
|
440 return (14); |
|
441 |
|
442 return (0); |
|
443 } |
|