winamp/Src/vlb/DolbyPayload.cpp
2024-09-24 14:54:57 +02:00

2271 lines
63 KiB
C++

/* $Header: /cvs/root/winamp/vlb/DolbyPayload.cpp,v 1.1 2009/04/28 20:21:07 audiodsp Exp $ */
/***************************************************************************\
*
* Copyright 2000-2002 Dolby Laboratories, Inc. All Rights
* Reserved. Do not copy. Do not distribute.
* Confidential information.
*
* filename: DolbyPayload.cpp
* project : MPEG-2 AAC Decoder
* contents/description: SE bitstream parsing routines
*
\***************************************************************************/
#include <assert.h>
#include "DolbyPayload.h"
/* Table of warnings returned by SE bitstream reading procedure, spectralExtInfo().
142 Invalid Dolby SE version number. This decoder only decodes Dolby SE v1.0.
143 Invalid Dolby SE version number. This decoder only decodes Dolby SE v1.0- v1.3.
144 Invalid Dolby SE number of bands to ignore.
146 Invalid # of Chans for Dolby SEv1.0 (only mono or stereo allowed. Check to see if adts_header.channel_config is valid.
147 Invalid Dolby SE spectral flatness measure.
148 Invalid Dolby SE noise shaping index.
149 Dolby SEv1.0: number of bytes read from bitstream != number of bytes in extension payload!
242 Attempt to read past end of fill element containing Dolby SE payload
*/
/* fDamp */
float baseband_dynamic_noise_shaping_index_lookup_table [] = {
1.00f,
0.98f,
0.96f,
0.90f,
0.84f,
0.60f,
0.30f,
0.00f
};
/* DNS (zlevel) values */
float q_2_unq_power_ratio_lookup_table [] = {
0.000000f,
0.030000f,
0.035755f,
0.042613f,
0.050787f,
0.060529f,
0.072140f,
0.085977f,
0.102470f,
0.122125f,
0.145551f,
0.173471f,
0.206746f,
0.246404f,
0.293669f,
0.350000f
};
/* Huffman codebooks for LONG,START, and STOP blocks */
Huffman se_hcb_long_lores_sorted_by_length[] = {
/* value, length, binary codeword */
{ 15, 2, 2},
{ 14, 2, 3},
{ 13, 3, 2},
{ 16, 3, 3},
{ 17, 4, 3},
{ 12, 5, 4},
{ 18, 5, 5},
{ 10, 6, 5},
{ 11, 6, 6},
{ 19, 6, 7},
{ 20, 7, 5},
{ 21, 7, 6},
{ 7, 7, 7},
{ 8, 7, 8},
{ 9, 7, 9},
{ 22, 8, 4},
{ 23, 8, 5},
{ 24, 8, 6},
{ 5, 8, 7},
{ 6, 8, 8},
{ 0, 8, 9},
{ 3, 9, 1},
{ 4, 9, 2},
{ 25, 9, 3},
{ 26, 9, 4},
{ 27, 9, 5},
{ 2, 9, 6},
{ 1, 9, 7},
{ 28, 10, 1},
{ 29, 11, 0},
{ 30, 11, 1}
};
/* this table will be used to determine codewords and codeword lengths once
the index of the codeword is known. N.B. that two tables are really not needed;
there are more efficient ways of looking up the codeword and its length
simultaneously, without two table lookups. However, we will adopt the Huffman decoding
style given in this codec which in general uses two tables to determine codeword and length. */
Huffman_lookup se_hcb_long_lores_sorted_by_index[] = {
/* index, length, codeword */
{ 0, 8, -15},
{ 1, 9, -14},
{ 2, 9, -13},
{ 3, 9, -12},
{ 4, 9, -11},
{ 5, 8, -10},
{ 6, 8, -9},
{ 7, 7, -8},
{ 8, 7, -7},
{ 9, 7, -6},
{ 10, 6, -5},
{ 11, 6, -4},
{ 12, 5, -3},
{ 13, 3, -2},
{ 14, 2, -1},
{ 15, 2, 0},
{ 16, 3, 1},
{ 17, 4, 2},
{ 18, 5, 3},
{ 19, 6, 4},
{ 20, 7, 5},
{ 21, 7, 6},
{ 22, 8, 7},
{ 23, 8, 8},
{ 24, 8, 9},
{ 25, 9, 10},
{ 26, 9, 11},
{ 27, 9, 12},
{ 28, 10, 13},
{ 29, 11, 14},
{ 30, 11, 15}
};
Huffman se_hcb_long_hires_sorted_by_length[] = {
/* index, length, codeword*/
{ 33, 3, 3},
{ 34, 3, 7},
{ 35, 3, 4},
{ 36, 3, 6},
{ 37, 3, 1},
{ 32, 4, 4},
{ 38, 4, 0},
{ 30, 5, 11},
{ 31, 5, 23},
{ 39, 5, 21},
{ 40, 5, 3},
{ 29, 6, 5},
{ 41, 6, 44},
{ 42, 6, 21},
{ 27, 7, 8},
{ 28, 7, 82},
{ 43, 7, 91},
{ 24, 8, 81},
{ 25, 8, 181},
{ 26, 8, 163},
{ 44, 8, 160},
{ 45, 8, 180},
{ 46, 8, 19},
{ 47, 8, 83},
{ 20, 9, 164},
{ 21, 9, 36},
{ 22, 9, 333},
{ 23, 9, 324},
{ 48, 9, 325},
{ 49, 9, 160},
{ 50, 9, 161},
{ 17, 10, 75},
{ 18, 10, 670},
{ 19, 10, 646},
{ 51, 10, 664},
{ 52, 10, 665},
{ 53, 10, 668},
{ 13, 11, 660},
{ 14, 11, 1342},
{ 15, 11, 1291},
{ 16, 11, 1290},
{ 54, 11, 1289},
{ 55, 11, 1288},
{ 56, 11, 1338},
{ 57, 11, 661},
{ 59, 11, 663},
{ 9, 12, 299},
{ 10, 12, 297},
{ 11, 12, 2591},
{ 12, 12, 2589},
{ 58, 12, 2588},
{ 60, 12, 2686},
{ 61, 12, 2590},
{ 62, 12, 2687},
{ 63, 12, 2679},
{ 64, 12, 1324},
{ 7, 13, 592},
{ 8, 13, 5356},
{ 65, 13, 596},
{ 66, 13, 593},
{ 4, 14, 5300},
{ 5, 14, 1194},
{ 6, 14, 10714},
{ 67, 14, 10715},
{ 68, 14, 5301},
{ 69, 14, 5302},
{ 0, 15, 10606},
{ 1, 15, 2390},
{ 3, 15, 2391},
{ 2, 16, 21214},
{ 70, 16, 21215}
};
/* this table will be used to determine codewords and codeword lengths once
the index of the codeword is known. N.B. that two tables are really not needed;
there are more efficient ways of looking up the codeword and its length
simultaneously, without two table lookups. However, we will adopt the Huffman decoding
style given in this codec which in general uses two tables to determine codeword and length. */
Huffman_lookup se_hcb_long_hires_sorted_by_index[] = {
/* index, length, value*/
{ 0, 15, -36},
{ 1, 15, -35},
{ 2, 16, -34},
{ 3, 15, -33},
{ 4, 14, -32},
{ 5, 14, -31},
{ 6, 14, -30},
{ 7, 13, -29},
{ 8, 13, -28},
{ 9, 12, -27},
{ 10, 12, -26},
{ 11, 12, -25},
{ 12, 12, -24},
{ 13, 11, -23},
{ 14, 11, -22},
{ 15, 11, -21},
{ 16, 11, -20},
{ 17, 10, -19},
{ 18, 10, -18},
{ 19, 10, -17},
{ 20, 9, -16},
{ 21, 9, -15},
{ 22, 9, -14},
{ 23, 9, -13},
{ 24, 8, -12},
{ 25, 8, -11},
{ 26, 8, -10},
{ 27, 7, -9},
{ 28, 7, -8},
{ 29, 6, -7},
{ 30, 5, -6},
{ 31, 5, -5},
{ 32, 4, -4},
{ 33, 3, -3},
{ 34, 3, -2},
{ 35, 3, -1},
{ 36, 3, 0},
{ 37, 3, 1},
{ 38, 4, 2},
{ 39, 5, 3},
{ 40, 5, 4},
{ 41, 6, 5},
{ 42, 6, 6},
{ 43, 7, 7},
{ 44, 8, 8},
{ 45, 8, 9},
{ 46, 8, 10},
{ 47, 8, 11},
{ 48, 9, 12},
{ 49, 9, 13},
{ 50, 9, 14},
{ 51, 10, 15},
{ 52, 10, 16},
{ 53, 10, 17},
{ 54, 11, 18},
{ 55, 11, 19},
{ 56, 11, 20},
{ 57, 11, 21},
{ 58, 12, 22},
{ 59, 11, 23},
{ 60, 12, 24},
{ 61, 12, 25},
{ 62, 12, 26},
{ 63, 12, 27},
{ 64, 12, 28},
{ 65, 13, 29},
{ 66, 13, 30},
{ 67, 14, 31},
{ 68, 14, 32},
{ 69, 14, 33},
{ 70, 16, 34}
};
/* Huffman codebooks for SHORT blocks */
/* Shortblock Tables derived from shortblock statistics only */
Huffman se_hcb_short_hires_sorted_by_length[] = {
/* index, length, codeword*/
{ 31, 3, 3},
{ 32, 3, 1},
{ 33, 3, 2},
{ 27, 4, 15},
{ 28, 4, 13},
{ 29, 4, 11},
{ 30, 4, 9},
{ 34, 4, 10},
{ 35, 4, 0},
{ 24, 5, 2},
{ 25, 5, 24},
{ 26, 5, 16},
{ 36, 5, 28},
{ 22, 6, 59},
{ 23, 6, 50},
{ 37, 6, 34},
{ 38, 6, 6},
{ 19, 7, 14},
{ 20, 7, 102},
{ 21, 7, 70},
{ 39, 7, 116},
{ 18, 8, 207},
{ 40, 8, 142},
{ 41, 8, 31},
{ 15, 9, 60},
{ 16, 9, 412},
{ 17, 9, 287},
{ 42, 9, 413},
{ 12, 10, 122},
{ 13, 10, 939},
{ 14, 10, 938},
{ 43, 10, 936},
{ 44, 10, 942},
{ 45, 10, 941},
{ 11, 11, 246},
{ 46, 11, 1886},
{ 52, 11, 1881},
{ 53, 11, 1880},
{ 7, 12, 494},
{ 8, 12, 2292},
{ 9, 12, 2290},
{ 10, 12, 2289},
{ 47, 12, 2291},
{ 48, 12, 2295},
{ 49, 12, 3748},
{ 50, 12, 2294},
{ 51, 12, 2288},
{ 54, 12, 3751},
{ 55, 12, 3775},
{ 58, 12, 3749},
{ 0, 13, 7501},
{ 5, 13, 7500},
{ 57, 13, 4586},
{ 60, 13, 991},
{ 2, 14, 1981},
{ 3, 14, 1980},
{ 4, 14, 15096},
{ 6, 14, 9175},
{ 59, 14, 9174},
{ 61, 14, 15097},
{ 1, 15, 30197},
{ 56, 15, 30196},
{ 62, 15, 30199},
{ 63, 15, 30198}
};
/* this table will be used to determine codewords and codeword lengths once
the index of the codeword is known. N.B. that two tables are really not needed;
there are more efficient ways of looking up the codeword and its length
simultaneously, without two table lookups. However, we will adopt the Huffman decoding
style given in this codec which in general uses two tables to determine codeword and length. */
Huffman_lookup se_hcb_short_hires_sorted_by_index[] = {
/* index, length, value*/
{ 0, 13, -34},
{ 1, 15, -33},
{ 2, 14, -32},
{ 3, 14, -31},
{ 4, 14, -30},
{ 5, 13, -29},
{ 6, 14, -28},
{ 7, 12, -27},
{ 8, 12, -26},
{ 9, 12, -25},
{ 10, 12, -24},
{ 11, 11, -23},
{ 12, 10, -22},
{ 13, 10, -21},
{ 14, 10, -20},
{ 15, 9, -19},
{ 16, 9, -18},
{ 17, 9, -17},
{ 18, 8, -16},
{ 19, 7, -15},
{ 20, 7, -14},
{ 21, 7, -13},
{ 22, 6, -12},
{ 23, 6, -11},
{ 24, 5, -10},
{ 25, 5, -9},
{ 26, 5, -8},
{ 27, 4, -7},
{ 28, 4, -6},
{ 29, 4, -5},
{ 30, 4, -4},
{ 31, 3, -3},
{ 32, 3, -2},
{ 33, 3, -1},
{ 34, 4, 0},
{ 35, 4, 1},
{ 36, 5, 2},
{ 37, 6, 3},
{ 38, 6, 4},
{ 39, 7, 5},
{ 40, 8, 6},
{ 41, 8, 7},
{ 42, 9, 8},
{ 43, 10, 9},
{ 44, 10, 10},
{ 45, 10, 11},
{ 46, 11, 12},
{ 47, 12, 13},
{ 48, 12, 14},
{ 49, 12, 15},
{ 50, 12, 16},
{ 51, 12, 17},
{ 52, 11, 18},
{ 53, 11, 19},
{ 54, 12, 20},
{ 55, 12, 21},
{ 56, 15, 22},
{ 57, 13, 23},
{ 58, 12, 24},
{ 59, 14, 25},
{ 60, 13, 26},
{ 61, 14, 27},
{ 62, 15, 28},
{ 63, 15, 29}
};
Huffman se_hcb_short_lores_sorted_by_length[] = {
/* index, length, codeword*/
{ 14, 2, 1},
{ 11, 3, 1},
{ 12, 3, 7},
{ 13, 3, 4},
{ 15, 3, 5},
{ 10, 4, 0},
{ 16, 4, 12},
{ 9, 5, 27},
{ 17, 5, 2},
{ 8, 6, 53},
{ 18, 6, 7},
{ 7, 7, 104},
{ 5, 8, 27},
{ 6, 8, 24},
{ 19, 8, 210},
{ 4, 9, 51},
{ 20, 9, 422},
{ 3, 10, 106},
{ 21, 10, 847},
{ 22, 10, 101},
{ 24, 10, 100},
{ 25, 10, 105},
{ 0, 11, 208},
{ 1, 11, 209},
{ 2, 11, 1693},
{ 23, 11, 1692},
{ 27, 11, 215},
{ 26, 12, 428},
{ 28, 12, 429}
};
/* this table will be used to determine codewords and codeword lengths once
the index of the codeword is known. N.B. that two tables are really not needed;
there are more efficient ways of looking up the codeword and its length
simultaneously, without two table lookups. However, we will adopt the Huffman decoding
style given in this codec which in general uses two tables to determine codeword and length. */
Huffman_lookup se_hcb_short_lores_sorted_by_index[] = {
/* index, length, value*/
{ 0, 11, -15},
{ 1, 11, -14},
{ 2, 11, -13},
{ 3, 10, -12},
{ 4, 9, -11},
{ 5, 8, -10},
{ 6, 8, -9},
{ 7, 7, -8},
{ 8, 6, -7},
{ 9, 5, -6},
{ 10, 4, -5},
{ 11, 3, -4},
{ 12, 3, -3},
{ 13, 3, -2},
{ 14, 2, -1},
{ 15, 3, 0},
{ 16, 4, 1},
{ 17, 5, 2},
{ 18, 6, 3},
{ 19, 8, 4},
{ 20, 9, 5},
{ 21, 10, 6},
{ 22, 10, 7},
{ 23, 11, 8},
{ 24, 10, 9},
{ 25, 10, 10},
{ 26, 12, 11},
{ 27, 11, 12},
{ 28, 12, 13}
};
/* Control table for Huffman Codebooks for all blocktypes and resolutions */
SE_power_resolution_table_struct SE_power_resolution_table[NUM_BLOCKTYPES][NUM_BANDRES_OPTIONS] =
{
/* powerResolution, cwLengthLookupTable, cwValueLookupTable, num_codewords */
/* SE_power_resolution_table[0][0,1]. Huffman codebooks for blocktype == 0 (LONG_WINDOW) */
{
{SE_BANDRES_2_67_DB, se_hcb_long_lores_sorted_by_length, se_hcb_long_lores_sorted_by_index, 31},
{SE_BANDRES_1_33_DB, se_hcb_long_hires_sorted_by_length, se_hcb_long_hires_sorted_by_index, 71}
},
/* SE_power_resolution_table[1][0,1]. Huffman codebooks for blocktype == 1 (START_WINDOW) */
{
{SE_BANDRES_2_67_DB, se_hcb_long_lores_sorted_by_length, se_hcb_long_lores_sorted_by_index, 31},
{SE_BANDRES_1_33_DB, se_hcb_long_hires_sorted_by_length, se_hcb_long_hires_sorted_by_index, 71}
},
/* SE_power_resolution_table[2][0,1]. Huffman codebooks for blocktype == 2 (SHORT_WINDOW) */
{
{SE_BANDRES_2_67_DB, se_hcb_short_lores_sorted_by_length, se_hcb_short_lores_sorted_by_index, 29},
{SE_BANDRES_1_33_DB, se_hcb_short_hires_sorted_by_length, se_hcb_short_hires_sorted_by_index, 64}
},
/* SE_power_resolution_table[3][0,1]. Huffman codebooks for blocktype == 3 (STOP_WINDOW) */
{
{SE_BANDRES_2_67_DB, se_hcb_long_lores_sorted_by_length, se_hcb_long_lores_sorted_by_index, 31},
{SE_BANDRES_1_33_DB, se_hcb_long_hires_sorted_by_length, se_hcb_long_hires_sorted_by_index, 71}
},
};
// tables for computeSeBandInfo
// LONG,START,STOP blocks only
unsigned int SE_bands_bw_44_48_1024[] = {
1,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,
2,3,3,3,3,3,3,3,3,4,
4,4,4,4,5,5,5,6,6,6,
7,7,8,8,8,9,9,10,10,11,
11,12,13,13,14,14,15,16,17,19,
20,23,25,28,33,39,46,58,74,100,
147
};
unsigned int SE_bands_bw_32_1024[] = {
2,2,2,2,2,2,2,2,3,3,
3,3,3,3,3,3,3,3,3,3,
3,3,3,3,4,4,4,4,4,4,
5,5,5,5,6,6,6,6,7,7,
8,8,9,9,10,10,11,12,13,13,
14,15,15,16,17,18,19,20,21,22,
23,24,26,28,31,34,38,43,50,59,
71,89
};
unsigned int SE_bands_bw_24_22_1024[] = {
2,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,4,4,4,4,
4,4,4,4,4,5,5,5,5,5,
5,6,6,6,7,7,7,8,8,8,
9,10,10,11,11,12,13,14,15,16,
16,17,18,19,20,21,22,23,24,25,
27,28,30,32,34,37,40,44,49,55,
64
};
unsigned int SE_bands_bw_16_12_11_1024[] = {
1,4,4,4,4,4,4,4,5,5,
5,5,5,5,5,5,5,5,5,5,
5,6,6,6,6,6,7,7,7,7,
8,8,8,9,9,9,10,10,11,11,
12,13,14,14,15,16,17,18,20,21,
22,23,25,26,28,29,31,32,34,35,
37,38,40,43,45,49
};
unsigned int SE_bands_bw_8_1024[] = {
8,8,8,8,8,8,8,8,9,9,
9,9,9,9,9,9,10,10,10,10,
10,11,11,11,12,12,12,13,13,14,
14,15,15,16,17,17,18,19,20,21,
22,24,25,26,28,30,32,34,36,38,
41,43,46,50
};
SE_Band_Info_struct SE_Band_Info_1024[] = {
/* sr SE_bw_table max_num_se_bands num_ignored_upper_bands */
{48000, SE_bands_bw_44_48_1024, 71, 1 },
{44100, SE_bands_bw_44_48_1024, 71, 1 },
{32000, SE_bands_bw_32_1024, 72, 0 },
{24000, SE_bands_bw_24_22_1024, 71, 0 },
{22050, SE_bands_bw_24_22_1024, 71, 0 },
{16000, SE_bands_bw_16_12_11_1024, 66, 0 },
{12000, SE_bands_bw_16_12_11_1024, 66, 0 },
{11025, SE_bands_bw_16_12_11_1024, 66, 0 },
{8000, SE_bands_bw_8_1024, 54, 0 },
{0, 0, 0, 0 }
};
unsigned int SE_bands_bw_44_48_2048[] = {
2,3,3,3,3,3,3,3,3,3,
3,3,3,3,3,3,4,4,4,4,
4,4,4,4,4,5,5,5,5,5,
5,6,6,6,7,7,7,8,8,8,
9,10,10,11,12,12,13,14,15,16,
17,18,19,20,20,21,22,24,25,26,
27,29,30,32,35,37,41,45,50,57,
65,77,92,115,148,201,293
};
unsigned int SE_bands_bw_32_2048[] = {
2,4,4,4,4,4,4,4,5,5,
5,5,5,5,5,5,5,5,5,5,
5,6,6,6,6,6,7,7,7,7,
8,8,8,9,9,9,10,10,11,12,
12,13,14,15,15,16,17,19,20,21,
22,24,25,26,28,29,31,32,34,35,
37,39,41,43,46,49,52,56,62,68,
76,86,99,117,141,177
};
unsigned int SE_bands_bw_24_22_2048[] = {
4,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,7,7,7,7,
7,7,8,8,8,8,9,9,9,10,
10,10,11,11,12,12,13,14,14,15,
16,17,18,19,20,21,23,24,26,27,
29,31,33,35,37,38,40,42,44,46,
49,51,53,56,59,63,68,73,79,87,
97,109,127
};
unsigned int SE_bands_bw_16_12_11_2048[] = {
3,8,8,8,8,8,8,8,9,9,
9,9,9,9,9,9,9,10,10,10,
10,10,11,11,11,12,12,12,13,13,
14,14,15,15,16,17,18,19,19,20,
22,23,24,25,27,29,30,32,34,37,
39,41,44,47,49,52,55,58,61,64,
67,70,73,77,80,85,90,97
};
unsigned int SE_bands_bw_8_2048[] = {
14,16,16,16,16,16,16,16,17,17,
17,17,17,18,18,18,18,19,19,20,
20,21,21,22,22,23,24,24,25,26,
27,28,29,30,32,33,35,36,38,40,
42,45,47,50,53,56,60,63,67,72,
76,81,86,91,98
};
SE_Band_Info_struct SE_Band_Info_2048[] = {
/* sr SE_bw_table max_num_se_bands num_ignored_upper_bands */
{48000, SE_bands_bw_44_48_2048, 77, 1 },
{44100, SE_bands_bw_44_48_2048, 77, 1 },
{32000, SE_bands_bw_32_2048, 76, 0 },
{24000, SE_bands_bw_24_22_2048, 73, 0 },
{22050, SE_bands_bw_24_22_2048, 73, 0 },
{16000, SE_bands_bw_16_12_11_2048, 68, 0 },
{12000, SE_bands_bw_16_12_11_2048, 68, 0 },
{11025, SE_bands_bw_16_12_11_2048, 68, 0 },
{8000, SE_bands_bw_8_2048, 55, 0 },
{0, 0, 0, 0 }
};
/* Short block tables for which SE band resolution is 1.0 critical bands */
// tables for computeSeBandInfo
// SHORT block only, for blocklength = 2048 samples (normal AAC blocklength: USE_AAC_XFORM is #defined)
// created from compute_se_band_info.m with parameters: N=256; Res = 1.0
unsigned int SE_bands_bw_44_48_128[] = {
1,1,1,1,1,1,1,2,2,3,
3,4,5,5,6,8,11,18,43
};
unsigned int SE_bands_bw_32_128[] = {
1,1,1,1,2,2,2,2,3,3,
4,5,6,7,8,10,12,17,30
};
unsigned int SE_bands_bw_24_22_128[] = {
2,2,2,2,2,2,3,3,4,4,
5,6,8,9,11,13,16,23
};
unsigned int SE_bands_bw_16_12_11_128[] = {
1,2,2,2,2,2,3,3,3,4,
4,5,6,8,10,11,13,16,20
};
unsigned int SE_bands_bw_8_128[] = {
1,4,4,4,4,4,5,5,6,6,
7,9,10,13,15,20
};
SE_Band_Info_struct SE_Band_Info_128[] = {
/* sr SE_bw_table max_num_se_bands num_ignored_upper_bands */
{48000, SE_bands_bw_44_48_128, 19, 0 },
{44100, SE_bands_bw_44_48_128, 19, 0 },
{32000, SE_bands_bw_32_128, 19, 0 },
{24000, SE_bands_bw_24_22_128, 18, 0 },
{22050, SE_bands_bw_24_22_128, 18, 0 },
{16000, SE_bands_bw_16_12_11_128, 19, 0 },
{12000, SE_bands_bw_16_12_11_128, 19, 0 },
{11025, SE_bands_bw_16_12_11_128, 19, 0 },
{8000, SE_bands_bw_8_128, 16, 0 },
{0, 0, 0, 0 }
};
// tables for computeSeBandInfo
// SHORT block only, for blocklength = 2048 samples (normal AAC blocklength: USE_AAC_XFORM is #defined)
// created from compute_se_band_info.m with parameters: N=512; Res = 1.0
unsigned int SE_bands_bw_44_48_256[] = {
2,2,2,2,2,2,3,3,3,4,
5,6,8,9,11,12,16,21,36,86
};
unsigned int SE_bands_bw_32_256[] = {
1,2,2,2,2,2,3,3,3,4,
4,5,6,8,10,12,14,16,19,24,
34,59
};
unsigned int SE_bands_bw_24_22_256[] = {
1,3,3,3,3,3,3,4,4,5,
6,7,9,11,13,15,18,21,25,32,
46
};
unsigned int SE_bands_bw_16_12_11_256[] = {
1,4,4,4,4,4,5,5,6,6,
7,9,10,13,15,19,23,27,31,38
};
unsigned int SE_bands_bw_8_256[] = {
7,7,7,7,8,8,9,10,11,13,
15,17,21,25,31,39
};
SE_Band_Info_struct SE_Band_Info_256[] = {
/* sr SE_bw_table max_num_se_bands num_ignored_upper_bands */
{48000, SE_bands_bw_44_48_256, 20, 0 },
{44100, SE_bands_bw_44_48_256, 20, 0 },
{32000, SE_bands_bw_32_256, 22, 0 },
{24000, SE_bands_bw_24_22_256, 21, 0 },
{22050, SE_bands_bw_24_22_256, 21, 0 },
{16000, SE_bands_bw_16_12_11_256, 20, 0 },
{12000, SE_bands_bw_16_12_11_256, 20, 0 },
{11025, SE_bands_bw_16_12_11_256, 20, 0 },
{8000, SE_bands_bw_8_256, 16, 0 },
{0, 0, 0, 0 }
};
float random(long *seed)
{
*seed = (1664525L * *seed) + 1013904223L;
return((float)(*seed) * (1.0f / 2.14749e+9f));
}
void noiseGen(float noise[], int nsamp)
{
int bin;
float sigma = 0., mean = 0.;
static int count = 0, initialized = 0;
static long curNoiseState = 101L;
static float noiseBuf[NOISE_LENGTH];
#ifdef TRI_NOISE
static float noiseBuf2[NOISE_LENGTH];
#endif
if(initialized == 0)
{
for (bin = 0; bin < NOISE_LENGTH; bin++)
{
noiseBuf[bin] = (float) random(&curNoiseState);
mean += noiseBuf[bin];
}
mean /= (float) NOISE_LENGTH;
for (bin = 0; bin < NOISE_LENGTH; bin++)
{
noiseBuf[bin] -= mean;
sigma += noiseBuf[bin] * noiseBuf[bin];
}
sigma = (float) sqrt(sigma / (double) NOISE_LENGTH);
for (bin = 0; bin < NOISE_LENGTH; bin++)
{
noiseBuf[bin] /= sigma;
}
#ifdef TRI_NOISE
sigma = 0.;
mean = 0.;
for (bin = 0; bin < NOISE_LENGTH; bin++)
{
noiseBuf2[bin] = (float) random(&curNoiseState);
mean += noiseBuf2[bin];
}
mean /= (float) NOISE_LENGTH;
for (bin = 0; bin < NOISE_LENGTH; bin++)
{
noiseBuf2[bin] -= mean;
sigma += noiseBuf2[bin] * noiseBuf2[bin];
}
sigma = (float) sqrt(sigma / (double) NOISE_LENGTH);
for (bin = 0; bin < NOISE_LENGTH; bin++)
{
noiseBuf2[bin] /= sigma;
}
for (bin = 0; bin < NOISE_LENGTH; bin++)
{
noiseBuf[bin] = (noiseBuf[bin] + noiseBuf2[bin]) / 2;
}
#endif
initialized = 1;
}
for (bin = 0; bin < nsamp; bin++)
{
count++;
count %= NOISE_LENGTH;
noise[bin] = noiseBuf[count];
}
}
/* This function computes the average energy in each SE band for all bands */
void computeAvgCopyEnergies(float* pfData,
int iCopyStart,
int iCopyStop,
int num_se_bands,
int* piBands,
int halfWindowLength,
int iWindowSequence,
float* avgCopyEnergies)
{
int iCopyPtr;
int iDestPtr;
int iBinCounter,iBandCounter;
#ifdef DEBUG_PRINT_BUFFER_MODEL
// print out buffer model
static int already_printed_out_buffer_model = 0;
#endif
/* initialize avgCopyEnergies to zero */
for (iBandCounter=0;iBandCounter<num_se_bands;iBandCounter++)
{
avgCopyEnergies[iBandCounter]=0.f;
}
/* initialize the buffer model */
#ifdef NEW_BUFFER_MODEL
iCopyPtr = iCopyStart + (iCopyStop - iCopyStart) % ((iWindowSequence == 2) ? 2 : 16);
#else
iCopyPtr = iCopyStart;
#endif
iDestPtr = iCopyStop;
for (iBandCounter=0;iBandCounter<num_se_bands;iBandCounter++)
{
#ifdef NEW_BUFFER_MODEL
// new buffer model for longs
// if we don't have enough continuous region in the baseband
// copy region, then we need to reset the copy pointer.
// 1) start the pointer at iCopyStart, which is 96 for
// long blocks and 12 for short blocks.
// N.B. that this setting must be done by the caller of spectralExtend()
// 2) we need to add to iCopyPtr the number of bins which will bring:
// a) for short blocks: the distance between iCopyPtr and iDestPtr
// to an EVEN number. By doing this, we can avoid having to deal with
// phase flipping issues. This additional "offset" is equal to (iDestPtr-iCopyStart) % 2
// b) for non short blocks: the distance between iCopyPtr and iDestPtr
// to an exact multiple of 16. 16 is chosen because it is divisible by 8 - in this manner,
// we can exactly match tones found in long block bins to short block bins. We also
// incorporate another factor of 2 here (2*8=16) so that the copying is done on boundaries
// of 2 short block bins. By doing this, we can avoid having to copy short block information
// an odd number of short block bins, and thus avoid a phase flip.
// new buffer model for longs
if (iCopyPtr + piBands[iBandCounter] > iCopyStop)
{
iCopyPtr = iCopyStart + (iDestPtr-iCopyStart) % ((iWindowSequence == 2) ? 2 : 16);
}
#else
// old buffer model for longs
if (iCopyPtr + piBands[iBandCounter] > iCopyStop)
{
iCopyPtr = iCopyStart;
if ((iDestPtr-iCopyPtr)%2)
{
iCopyPtr++;
}
}
#endif
// simulate band loop in spectral extend
for(iBinCounter=0;iBinCounter<piBands[iBandCounter];iBinCounter++)
{
float fTemp;
fTemp=pfData[iCopyPtr];
avgCopyEnergies[iBandCounter]+=(fTemp*fTemp);
#ifdef DEBUG_PRINT_BUFFER_MODEL
//print out buffer model
if (iWindowSequence == 2 &&
((already_printed_out_buffer_model == 0) || (already_printed_out_buffer_model == 1)) )
{
// extra zero is to distinguish this buffer model printout from other printouts
printf("%d %d 0\n",iDestPtr,iCopyPtr);
already_printed_out_buffer_model = 1;
}
#endif
iCopyPtr++;
iDestPtr++;
if (iCopyPtr >= iCopyStop)
{
iCopyPtr = iCopyStart + (iDestPtr-iCopyStart) % ((iWindowSequence == 2) ? 2 : 16);
}
} /* iBinCounter */
avgCopyEnergies[iBandCounter] /= (float) piBands[iBandCounter];
} /* iBandCounter */
#ifdef DEBUG_PRINT_BUFFER_MODEL
if (already_printed_out_buffer_model == 1)
{
already_printed_out_buffer_model = 2;
}
#endif
}
#ifdef DNS
void applyDNS( float *pfSpectralData,
DNS_INFORMATION_STRUCT*psDNSInfoStruct,
int iPrevWnd)
{
int bin, bnd, grp, sec, copyStop, qCount;
const int *sfBand;
#ifdef SIGNAL_SUB
int m;
int copyStart;
int step;
int bufLen;
int segment;
float ns_atten_hi, ns_atten_lo;
#endif
int zeroup, zerodown;
float normCopy[MAX_NUM_WINDOW_GROUPS][DOLBY_BLOCK_LEN_LONG], noiseEnvelope[MAX_NUM_WINDOW_GROUPS][DOLBY_BLOCK_LEN_LONG];
float power, ratio, qPower;
float startScale, prevScale, *coef;
float slope, intercept, scale, dither;
int winInGrp, windowBinOffset, windowNumber, numNoiseRecords;
static long curNoiseState = 0;
int attenSlopeThreshold;
int startBin;
int moduloCopyOffset;
// compute some preliminaries. These values do not change
// for all windows in the current frame.
copyStop = psDNSInfoStruct->iLastBin;
coef = pfSpectralData;
sfBand = psDNSInfoStruct->piBandOffsets;
numNoiseRecords = (psDNSInfoStruct->iWindowSequence == 2 ? 8 : 1);
// initialize noiseEnvelope, the noise mask for zero-valued mdct
// coefficients belonging to sections with non-zero huffman codebooks.
for (windowNumber=0;windowNumber<numNoiseRecords;windowNumber++)
{
for (bin = 0; bin < DOLBY_BLOCK_LEN_LONG; bin++)
{
noiseEnvelope[windowNumber][bin] = 0.;
}
}
#ifdef SIGNAL_SUB
/* Generate a unit-variance signal substitution vector */
// we'll need to generate substitution vectors for all windows in the group.
// these noise vectors will be used in two places in this function:
// dns and non-zero huffman codebook dithering.
windowBinOffset = 0;
windowNumber = 0;
if (psDNSInfoStruct->iWindowSequence != 2) /* Long, or transition block */
{
copyStart = SS_COPYSTART;
step = SS_STEP_LONG;
bufLen = SS_BUF_LEN_LONG;
attenSlopeThreshold = 19; /* slope change at bin 120 (long block). This is 2.58kHz for fs = 44.1kHz. */
startBin = START_BIN_LONG;
moduloCopyOffset = 14; /* offset to assure that any holes in the translation are not coincident with
holes in the target spectra. Only a problem with the first pass of the normCopy
modulo buffer */
ns_atten_hi = NS_ATTEN1_LONG;
ns_atten_lo = NS_ATTEN2_LONG;
}
else /* Short block */
{
copyStart = SS_COPYSTART / 8;
step = SS_STEP_SHORT;
bufLen = SS_BUF_LEN_SHORT;
attenSlopeThreshold = 4; /* slope change at bin 16 (short block). This is 2.75kHz for fs = 44.1kHz */
startBin = START_BIN_SHORT;
moduloCopyOffset = 7; /* see definition of moduloCopyOffset above for long blocks */
ns_atten_hi = NS_ATTEN1_SHORT;
ns_atten_lo = NS_ATTEN2_SHORT;
}
for(windowNumber = 0; windowNumber < numNoiseRecords; windowNumber++, windowBinOffset += 256)
{
for (bin = 0; bin < bufLen; bin++)
{
normCopy[windowNumber][bin] = coef[windowBinOffset + copyStart + bin];
}
for (segment = 0; segment < bufLen / step; segment++)
{
power = 0.;
qCount = 0;
for (m = 0; m < step; m++)
{
if (normCopy[windowNumber][segment * step + m] != 0.)
{
power += normCopy[windowNumber][segment * step + m] * normCopy[windowNumber][segment * step + m];
qCount++;
}
}
if (qCount)
{
power /= (float) qCount;
power = 1.0f / (float)(sqrt(power));
}
for (m = 0; m < step; m++)
{
if (normCopy[windowNumber][segment * step + m] == 0.)
{
normCopy[windowNumber][segment * step + m] = 1.5f * random(&curNoiseState);
}
else
{
normCopy[windowNumber][segment * step + m] *= power;
}
}
}
} // windowNumber
#else
/* Generate unit-variance random noise vector */
windowNumber = 0;
numNoiseRecords = (psDNSInfoStruct->iWindowSequence == 2 ? 8 : 1);
for(windowNumber=0;windowNumber<numNoiseRecords;windowNumber++)
{
power = 0.0f;
for (bin = 0; bin < DOLBY_BLOCK_LEN_LONG; bin++)
{
normCopy[windowNumber][bin] = random(&curNoiseState);
power += normCopy[windowNumber][bin] * normCopy[windowNumber][bin];
}
power /= (float) DOLBY_BLOCK_LEN_LONG;
power = 1.0f / (float) sqrt(power);
for (bin = 0; bin < DOLBY_BLOCK_LEN_LONG; bin++)
{
normCopy[windowNumber][bin] *= power;
}
}
#endif /* SIGNAL_SUB */
/* Compute DNS */
windowBinOffset = 0;
windowNumber = 0;
for (grp = 0; grp < psDNSInfoStruct->iGroupCount; grp++)
{
// this look increments the windowBinOffset index to reflect the 0th bin of the current
// window in the group. If there is more than one window in the current frame, then
// we are dealing with 8 short windows, and the data for each of these windows will
// be in the coef[] array spaced out at intervals of 256 samples. The interval will be
// 256 samples whether we're dealing with double or single length transforms.
for (winInGrp = 0; winInGrp < psDNSInfoStruct->iGroupLength[grp]; winInGrp++, windowNumber++, windowBinOffset += 256)
{
for (sec = 0; sec < psDNSInfoStruct->psSectionInfoStruct->aiSectionCount[grp]; sec++)
{
for (bnd = psDNSInfoStruct->psSectionInfoStruct->aaiSectionStart[grp][sec];
bnd < psDNSInfoStruct->psSectionInfoStruct->aaiSectionEnd[grp][sec]; bnd++)
{
qPower = 0.;
qCount = 0;
for (bin = sfBand[bnd]; bin < sfBand[bnd+1]; bin++)
{
if (coef[windowBinOffset+bin] != 0.0f)
{
qPower += coef[windowBinOffset+bin] * coef[windowBinOffset+bin];
qCount++;
}
} /* bin */
if (qCount)
{
ratio = psDNSInfoStruct->aafDNSRatio[grp][bnd] * (float) sqrt(qPower / (double) qCount);
for (bin = sfBand[bnd]; bin < sfBand[bnd+1]; bin++)
{
if (psDNSInfoStruct->iWindowSequence != 2) /* long/transition block */
{
if ((coef[windowBinOffset+bin] == 0.) && (bin >= startBin))
{
slope = (0.6f - 0.3f) / (float) (copyStop - startBin);
intercept = 0.3f- (50.0f * slope);
scale = slope * (float) bin + intercept;
#ifdef SIGNAL_SUB
coef[windowBinOffset+bin] = normCopy[windowNumber][bin % bufLen] * scale * ratio;
#else
coef[windowBinOffset+bin] = normCopy[windowNumber][bin] * scale * ratio;
#endif
}
}
else /* short block */
{
if ((coef[windowBinOffset+bin] == 0.) && (bin >= startBin))
{
#ifdef SIGNAL_SUB
coef[windowBinOffset+bin] = normCopy[windowNumber][bin % bufLen] * 0.8f * ratio;
#else
coef[windowBinOffset+bin] = normCopy[windowNumber][bin] * 0.3f * ratio;
#endif
}
}
} /* bin */
} /* if (qCount) */
} /* bnd */
} /* sec */
} /* WinInGrp */
} /* grp */
/* Compute dither for non-zero huffman codebooks, starting from DC and progressing upwards */
windowBinOffset = 0;
windowNumber = 0;
for (grp = 0; grp < psDNSInfoStruct->iGroupCount; grp++)
{
// this look increments the windowBinOffset index to reflect the 0th bin of the current
// window in the group. If there is more than one window in the current frame, then
// we are dealing with 8 short windows, and the data for each of these windows will
// be in the coef[] array spaced out at intervals of 256 samples. The interval will be
// 256 samples whether we're dealing with double or single length transforms.
for (winInGrp=0;winInGrp<psDNSInfoStruct->iGroupLength[grp];winInGrp++,windowNumber++,windowBinOffset+=256)
{
// initialize state variables for the filter
startScale = 0.;
prevScale = 0.;
for (bnd = 0; bnd < psDNSInfoStruct->iMaxSFB; bnd++)
{
for (bin = sfBand[bnd]; bin < sfBand[bnd+1]; bin++)
{
if (coef[windowBinOffset + bin] == 0.0f)
{
noiseEnvelope[windowNumber][bin] = startScale * GLOBAL_ATTEN;
startScale *= ((bin >= sfBand[attenSlopeThreshold]) ? ns_atten_hi : ns_atten_lo);
prevScale = 0.0f;
}
else
{
if (prevScale == 0.0f) /* This starts off the dither envelope */
{
startScale = (float)(fabs(coef[windowBinOffset+bin])) * NSFILT_COEF;
prevScale = startScale;
}
else /* dither is averaged as low-pass process */
{
startScale = (float)(fabs(coef[windowBinOffset+bin])) * NSFILT_COEF + prevScale * (1.0f - NSFILT_COEF);
prevScale = startScale;
}
}
} /* bin */
} /* bnd */
} /* winInGrp */
} /* grp */
/* Compute dither for non-zero huffman codebooks, starting from Fs/2 and progressing downwards */
windowBinOffset = 0;
windowNumber = 0;
for (grp = 0; grp < psDNSInfoStruct->iGroupCount; grp++)
{
for (winInGrp=0;winInGrp<psDNSInfoStruct->iGroupLength[grp];winInGrp++,windowNumber++,windowBinOffset+=256)
{
startScale = 0.;
prevScale = 0.;
for (bnd = psDNSInfoStruct->iMaxSFB - 1; bnd >= 0; bnd--)
{
for (bin = sfBand[bnd+1] - 1; bin >= sfBand[bnd]; bin--)
{
if (coef[windowBinOffset+bin] == 0.0f)
{
noiseEnvelope[windowNumber][bin] = DSPmax(noiseEnvelope[windowNumber][bin], (startScale * GLOBAL_ATTEN));
startScale *= ((bin >= sfBand[attenSlopeThreshold]) ? ns_atten_hi : ns_atten_lo);
startScale *= BACKWARD_MASK_COMP;
prevScale = 0.0f;
}
else
{
if (prevScale == 0.0f) /* This starts off the dither envelope */
{
startScale = (float)(fabs(coef[windowBinOffset+bin])) * NSFILT_COEF;
prevScale = startScale;
}
else /* dither is averaged as low-pass process */
{
startScale = (float)(fabs(coef[windowBinOffset+bin])) * NSFILT_COEF + prevScale * (1.0f - NSFILT_COEF);
prevScale = startScale;
}
}
} /* bin */
} /* bnd */
} /* winInGrp */
} /* grp */
// merge noise records and coefficient records
windowBinOffset = 0;
for(windowNumber=0;windowNumber<numNoiseRecords;windowNumber++,windowBinOffset+=256)
{
for (bin = startBin; bin < psDNSInfoStruct->iLastBin; bin++)
{
#ifdef SIGNAL_SUB
dither = normCopy[windowNumber][(bin + moduloCopyOffset) % bufLen];
#else
dither = normCopy[windowNumber][bin];
#endif
dither *= noiseEnvelope[windowNumber][bin];
zeroup = ((noiseEnvelope[windowNumber][bin+1] != 0.0f) ? 1 : 0);
zerodown = ((noiseEnvelope[windowNumber][bin-1] != 0.0f) ? 1 : 0);
if ((coef[windowBinOffset+bin] == 0.0) && (zeroup || zerodown))
{
coef[windowBinOffset+bin] = dither;
if ((psDNSInfoStruct->iWindowSequence == 3) && (iPrevWnd == 1)) /* done to support legacy bitstreams */
{
coef[windowBinOffset+bin] *= 0.5f;
}
}
} /* bin */
} /* windowNumber */
}
#endif /* DNS */
unsigned char computeSeBandInfo (unsigned int SRate, /* input: Sample Rate */
unsigned int first_SE_bin, /* input: bin number of the first bin of the extension range */
SE_Band_Info_struct* pSE_Band_Info_struct, /* input: SE Band info struct ptr */
int* SE_bands_bw, /* output: SE bandwidths, in bins (array; memory assumed to be already allocated) */
int* num_SE_bands)
{
int i;
unsigned int sum_bandwidths = 0;
int band_index = 0;
int distance_low, distance_high;
unsigned int* puiSE_bands_bw;
int band_containing_first_SE_bin;
/* find the right entry of SE_Band_Info to use based on the input sample rate */
while(pSE_Band_Info_struct->sr != SRate)
{
pSE_Band_Info_struct++;
if(pSE_Band_Info_struct->sr == 0)
{
/* FAILSAFE...rather than just getting stuck in this while() loop until we receive
* an access violation, assume we've received MAX_INCONSISTENT_BLOCKS number of blocks
* indicating double length x-form, when the bitstream is really still single length.
*
* If we've searched the SE_Band_Info_struct and not found a matching SR, assume the
* useAACTransform bit is incorrectly indicating double length transforms (0). So,
* divide SR by 2 and force the pSE_Band_Info_struct pointer to point to the
* 1024 point version.
*/
SRate >>= 1;
pSE_Band_Info_struct = SE_Band_Info_1024;
//printf("SE does not support the given sample rate.\n");
//exit(342);
}
}
/* find the closest entry in SE_bands_bw to first_SE_bin.
count the number of se bands.*/
puiSE_bands_bw = pSE_Band_Info_struct->SE_bands_bw;
sum_bandwidths = 0;
band_containing_first_SE_bin = 0;
while(sum_bandwidths < first_SE_bin)
{
distance_low = first_SE_bin - sum_bandwidths;
sum_bandwidths += *puiSE_bands_bw++;
band_containing_first_SE_bin++;
}
distance_high = first_SE_bin - sum_bandwidths;
if (distance_low < -distance_high)
{
/* Lower band edge was closer to first_SE_bin */
band_containing_first_SE_bin--;
puiSE_bands_bw--;
}
*num_SE_bands = pSE_Band_Info_struct->SE_max_num_se_bands - band_containing_first_SE_bin;
/* copy the bandwidth information into the Lines array */
for(i=0;i<*num_SE_bands; i++)
SE_bands_bw[i] = *puiSE_bands_bw++;
/* perform SE band shrinkage / expansion to make first_SE_bin be the first bin of the first
extension band */
i = *num_SE_bands - 1;
if (distance_low <= -distance_high)
{
/* round-robin decrease band sizes */
while(distance_low > 0)
{
SE_bands_bw[i]--;
i--;
if(i<0) i = *num_SE_bands - 1;
distance_low--;
}
} else {
/* round-robin decrease band sizes */
while(-distance_high > 0)
{
SE_bands_bw[i]++;
i--;
if(i<0) i = *num_SE_bands - 1;
distance_high++;
}
}
assert(pSE_Band_Info_struct->SE_num_ignored_upper_bands >= 0);
assert(pSE_Band_Info_struct->SE_num_ignored_upper_bands <= ((1<<SE_BAND_IGNORE_BITS)-1));
/* REMOVED IN FAVOR OF ABOVE ASSERTIONS */
/*
if (pSE_Band_Info_struct->SE_num_ignored_upper_bands < 0 ||
pSE_Band_Info_struct->SE_num_ignored_upper_bands > ((1<<SE_BAND_IGNORE_BITS)-1) )
{
//printf("SE error: number of ignored bands must be between 0 and 7, inclusive.\n");
//exit(343);
}*/
/* return the number of bands to ignore */
return (pSE_Band_Info_struct->SE_num_ignored_upper_bands);
}
float decompressSEWeights(int logWeight, int resolution)
{
static int init = 0;
static float invLogTable[2][256];
int n;
float weight;
if (!init)
{
for (n = 0; n < 256; n++)
{
invLogTable[SE_BANDRES_2_67_DB][n] = (float) pow(10.0, ((double) n - 32.0) / 3.75);
invLogTable[SE_BANDRES_1_33_DB][n] = (float) pow(10.0, ((double) n - 32.0) / 7.50);
}
init++;
}
if (logWeight < -32)
{
logWeight = -32;
}
/* some error checking
return a very small power if there is a problem with the resolution value */
if (resolution == SE_BANDRES_2_67_DB || resolution == SE_BANDRES_1_33_DB) {
weight = invLogTable[resolution][logWeight + 32];
} else {
weight = invLogTable[0][0];
}
return(weight);
}
void computeLPC(float*pfData, int order, int iStart, int iStop, float *alpha)
{
int n, lag;
float rxx[10];
/* Compute autocorrelation */
for (lag = 0; lag < order + 1; lag++)
{
rxx[lag] = 0.f;
for (n = iStart; n < iStop - lag; n++)
{
rxx[lag] += pfData[n] * pfData[n+lag];
}
}
if (rxx[0] != 0.f)
{
for (lag = 1; lag < order + 1; lag++)
{
rxx[lag] /= rxx[0];
}
rxx[0] /= rxx[0];
}
else
{
rxx[0] = 1.0f;
for (lag = 1; lag < order + 1; lag++)
{
rxx[lag] = 0.f;
}
}
/* Compute 2nd order predictor coefficients */
alpha[0] = rxx[1] * (1.0f - rxx[2]) / (1.0f - rxx[1] * rxx[1]);
alpha[1] = (rxx[2] - rxx[1] * rxx[1]) / (1.0f - rxx[1] * rxx[1]);
}
void synthesisFilter(float *Data, float *alpha, float fDamp, int length)
{
int k, n;
float power, state[SE_NSHAPE_ORDER] = {0.};
power = 0;
alpha[0] *= fDamp;
alpha[1] *= (fDamp * fDamp);
for (n = 0; n < length; n++)
{
for (k = 0; k < SE_NSHAPE_ORDER; k++)
{
Data[n] += alpha[k] * state[k];
}
for (k = SE_NSHAPE_ORDER - 1; k > 0; k--)
{
state[k] = state[k-1];
}
state[0] = Data[n];
power += Data[n] * Data[n];
}
/* Re-normalize to unit variance */
if (power != 0.)
{
power /= (float) length;
power = 1.0f / (float) sqrt(power);
for (n = 0; n < length; n++)
{
Data[n] *= power;
}
}
}
inline int readPastEndOfFillElement(int cnt, int numBitsRead, int numBitsToRead)
{
if (numBitsRead + numBitsToRead > cnt * 8)
{
return (1);
}
else
{
return (0);
}
}
// This function returns -(num_bits_used) if it attempts to read beyond the end of the fill element.
// Otherwise, it returns a positive integer corresponding to the index of the decoded Huffman codeword.
int decodeHuffCw(Huffman *h,
CDolbyBitStream*poBitStream,
int cnt,
int numBitsUsed)
{
int i, j;
unsigned long cw;
i = h->len;
// test for read past end of fill element
if (readPastEndOfFillElement(cnt,numBitsUsed,i))
{
return (-numBitsUsed);
}
cw = poBitStream->Get(i);
numBitsUsed += i;
while (cw != h->cw)
{
h++;
j = h->len-i;
i += j;
cw <<= j;
// test for read past end of fill element
if (readPastEndOfFillElement(cnt,numBitsUsed,j))
{
return (-numBitsUsed);
}
cw |= poBitStream->Get(j);
numBitsUsed += j;
}
return(h->index);
}
int spectralExtInfo(int cnt, DOLBY_PAYLOAD_STRUCT *seData,CDolbyBitStream*poBitStream)
{
int max_sfb[2];
int n=0;
int num_bits_used;
int num_leftover_bits = 0;
int last_valid_q_2_unq_power_ratio = 0;
long get_bits_return_buffer;
int powerval_index;
int iNumDNSBits;
int iNumSpectFlatBits;
int ch_index,grp_index;
int i;
int num_chans_present;
int num_ref_energy_bits_to_read;
int start_sfb, end_sfb, sfb_index;
float q_2_unq_power_ratio;
max_sfb[0]=seData->aiMaxSFB[0];
max_sfb[1]=seData->aiMaxSFB[1];
/* set error flag to zero as a default */
seData->iDolbyBitStreamWarning = 0;
/* Account for the bits used to describe the extension type EXT_SE_DATA.
This data has already been read from the datastream */
num_bits_used = 4;
/* get version_id */
// test for read past end of fill element
if (readPastEndOfFillElement(cnt,num_bits_used,3))
{
seData->iDolbyBitStreamWarning = 242;
return ((cnt*8) - num_bits_used);
}
get_bits_return_buffer = poBitStream->Get(3);
num_bits_used += 3;
if (get_bits_return_buffer >= 4)
{
// Invalid Dolby SE version number. This decoder only decodes Dolby SE v1.0- v1.3.
seData->iDolbyBitStreamWarning = 142;
return ((cnt*8) - num_bits_used);
}
/* get reserved bits */
// test for read past end of fill element
if (readPastEndOfFillElement(cnt,num_bits_used,2))
{
seData->iDolbyBitStreamWarning = 242;
return ((cnt*8) - num_bits_used);
}
get_bits_return_buffer = poBitStream->Get(2);
num_bits_used += 2;
/* N.B. the reserve bits are not checked against any specific value,
since the reserve bits might depend on the revision number. Since we
are allowing multiple SE versions to be decoded by this decoder, the
reserve bits cannot be known for sure. */
/* Get iSEPowerResolution parameter from bitstream */
// test for read past end of fill element
if (readPastEndOfFillElement(cnt,num_bits_used,1))
{
seData->iDolbyBitStreamWarning = 242;
return ((cnt*8) - num_bits_used);
}
get_bits_return_buffer = poBitStream->Get(1);
num_bits_used += 1;
seData->iSEPowerResolution = get_bits_return_buffer;
/* get single length x-form bit (1 = single length, 0 = double length) */
// test for read past end of fill element
if (readPastEndOfFillElement(cnt,num_bits_used,1))
{
seData->iDolbyBitStreamWarning = 242;
return ((cnt*8) - num_bits_used);
}
get_bits_return_buffer = poBitStream->Get(1);
num_bits_used += 1;
#ifdef USE_XFORM_HYSTERESIS
static int iConsistentBlockCount = 0;
static int iPreviousDoubleLengthXFormFlag = 2; //Init to invalid value so that first block is considered "consistent" */
#endif
if (get_bits_return_buffer)
{
/* Bit set indicates single length x-form */
#ifdef USE_XFORM_HYSTERESIS
if (iPreviousDoubleLengthXFormFlag == 1)
{
/* Last block indicated double length x-form, current block indicates single. */
if (++iConsistentBlockCount == XFORM_HYSTERESIS_LENGTH)
{
seData->iUsesDoubleLengthXForm = 0;
iConsistentBlockCount = 0;
}
else
{
seData->iUsesDoubleLengthXForm = 1;
}
}
else
{
seData->iUsesDoubleLengthXForm = 0;
iConsistentBlockCount = 0;
}
#else
seData->iUsesDoubleLengthXForm = 0;
#endif
}
else
{
/* Bit clear indicates double length */
#ifdef USE_XFORM_HYSTERESIS
if (iPreviousDoubleLengthXFormFlag == 0)
{
/* Last block indicated single length x-form, current block indicates double. */
if (++iConsistentBlockCount == XFORM_HYSTERESIS_LENGTH)
{
seData->iUsesDoubleLengthXForm = 1;
iConsistentBlockCount = 0;
}
else
{
seData->iUsesDoubleLengthXForm = 0;
}
}
else
{
seData->iUsesDoubleLengthXForm = 1;
iConsistentBlockCount = 0;
}
#else
seData->iUsesDoubleLengthXForm = 1;
#endif
}
#ifdef USE_XFORM_HYSTERESIS
iPreviousDoubleLengthXFormFlag = seData->iUsesDoubleLengthXForm;
#endif
/* verify that the source bitstream is either mono or stereo */
num_chans_present = seData->iChannels;
if(num_chans_present < 1 || num_chans_present > 2)
{
// Invalid # of Chans for Dolby SEv1.0 (only mono or stereo allowed. Check to see if adts_header.channel_config is valid.
seData->iDolbyBitStreamWarning = 146;
return ((cnt*8) - num_bits_used);
}
for(ch_index=0;ch_index<num_chans_present;ch_index++)
{
if (seData->asDNSInfoStruct[ch_index].iWindowSequence == 2)
{
iNumDNSBits = SE_DNS_PWR_BITS_SHORT;
iNumSpectFlatBits = SE_SPECT_FLAT_BITS_SHORT;
}
else
{
iNumDNSBits = SE_DNS_PWR_BITS_LONG;
iNumSpectFlatBits = SE_SPECT_FLAT_BITS_LONG;
}
/* get number of bands to ignore */
// test for read past end of fill element
if (readPastEndOfFillElement(cnt,num_bits_used,3))
{
seData->iDolbyBitStreamWarning = 242;
return ((cnt*8) - num_bits_used);
}
get_bits_return_buffer = poBitStream->Get(3);
num_bits_used += 3;
if ( (get_bits_return_buffer < 0) || (get_bits_return_buffer > 7) )
{
// Invalid Dolby SE number of bands to ignore.
seData->iDolbyBitStreamWarning = 144;
return ((cnt*8) - num_bits_used);
}
seData->SE_num_ignored_upper_bands[ch_index] = get_bits_return_buffer;
for(grp_index=0;grp_index<seData->iGroupCount[ch_index];grp_index++)
{
/* get spectral flatness measure */
// test for read past end of fill element
if (readPastEndOfFillElement(cnt,num_bits_used,8))
{
seData->iDolbyBitStreamWarning = 242;
return ((cnt*8) - num_bits_used);
}
get_bits_return_buffer = poBitStream->Get(iNumSpectFlatBits);
num_bits_used += iNumSpectFlatBits;
if ( (get_bits_return_buffer < 0) || (get_bits_return_buffer > (1 << iNumSpectFlatBits) - 1) )
{
// Invalid Dolby SE spectral flatness measure.
seData->iDolbyBitStreamWarning = 147;
return ((cnt*8) - num_bits_used);
}
seData->sfm[ch_index][grp_index] = get_bits_return_buffer;
/* get baseband_dynamic_noise_shaping_index */
// test for read past end of fill element
if (readPastEndOfFillElement(cnt,num_bits_used,3))
{
seData->iDolbyBitStreamWarning = 242;
return ((cnt*8) - num_bits_used);
}
if (seData->asDNSInfoStruct[ch_index].iWindowSequence != 2)
{
get_bits_return_buffer = poBitStream->Get(3);
num_bits_used += 3;
if ( (get_bits_return_buffer < 0) || (get_bits_return_buffer > 7) )
{
// Invalid Dolby SE noise shaping index.
seData->iDolbyBitStreamWarning = 148;
return ((cnt*8) - num_bits_used);
}
seData->fdamp[ch_index][grp_index] = baseband_dynamic_noise_shaping_index_lookup_table[get_bits_return_buffer];
}
else
{
seData->fdamp[ch_index][grp_index] = baseband_dynamic_noise_shaping_index_lookup_table[0];
}
/* get dolby DNS information */
/* nsect_export, and sect_export taken directly from huffdec2.c: getics().
even values for the second index = the hcb values for that section;
odd values for the second index = the last valid sfb index for that section + 1 */
for(i=0;i<seData->asDNSInfoStruct[ch_index].psSectionInfoStruct->aiSectionCount[grp_index];i++)
{
/* compute starting and ending sfb numbers for this hcb section */
start_sfb = seData->asDNSInfoStruct[ch_index].psSectionInfoStruct->aaiSectionStart[grp_index][i];
end_sfb = seData->asDNSInfoStruct[ch_index].psSectionInfoStruct->aaiSectionEnd[grp_index][i];
if ((seData->asDNSInfoStruct[ch_index].psSectionInfoStruct->aaiSectionCodebooks[grp_index][i] > 0) &&
(seData->asDNSInfoStruct[ch_index].psSectionInfoStruct->aaiSectionCodebooks[grp_index][i] < 12))
{
// test for read past end of fill element
if (readPastEndOfFillElement(cnt,num_bits_used, iNumDNSBits))
{
seData->iDolbyBitStreamWarning = 242;
return ((cnt*8) - num_bits_used);
}
get_bits_return_buffer = poBitStream->Get(iNumDNSBits);
num_bits_used += iNumDNSBits;
if (seData->asDNSInfoStruct[ch_index].iWindowSequence == 2)
{
q_2_unq_power_ratio = q_2_unq_power_ratio_lookup_table[2 * get_bits_return_buffer + 1];
}
else
{
q_2_unq_power_ratio = q_2_unq_power_ratio_lookup_table[get_bits_return_buffer];
}
}
else
{
/* For HCB's >0 and <12, q_2_unq_power_ratio for the section should never be used.
However, we'll set the value to 0.0f to be safe, effectively turning DNS off for
this HCB section. */
q_2_unq_power_ratio = 0.0f;
}
/* assign the zpower value just read from the bitstream to the sfb's to
which the current section corresponds. */
for (sfb_index = start_sfb; sfb_index<end_sfb; sfb_index++)
{
seData->asDNSInfoStruct[ch_index].aafDNSRatio[grp_index][sfb_index] = q_2_unq_power_ratio;
}
}
/* get power normalization values */
/* first, determine the number of se bands in the datastream.
to do this, we'll use computeSeBandInfo. */
if (max_sfb[ch_index] == 0)
{
seData->num_se_bands[ch_index] = 0;
}
else
{
// decide which lookup table to use when determining
// the se banding structure for the current frame.
// this is a function of transform size and window type
SE_Band_Info_struct* pSE_Band_Info_table_to_use;
if (seData->asDNSInfoStruct[ch_index].iWindowSequence == 2)
{
// SHORT window
if (seData->iUsesDoubleLengthXForm)
{
pSE_Band_Info_table_to_use = SE_Band_Info_256;
}
else
{
pSE_Band_Info_table_to_use = SE_Band_Info_128;
}
}
else
{
// LONG,START,or STOP window
if (seData->iUsesDoubleLengthXForm)
{
pSE_Band_Info_table_to_use = SE_Band_Info_2048;
}
else
{
pSE_Band_Info_table_to_use = SE_Band_Info_1024;
}
}
computeSeBandInfo ((seData->iUsesDoubleLengthXForm) ? (2 * seData->iSampleRate) : seData->iSampleRate,
seData->aiCopyStop[ch_index],
pSE_Band_Info_table_to_use,
seData->seBands[ch_index][grp_index],
&seData->num_se_bands[ch_index]);
seData->num_se_bands[ch_index] -= seData->SE_num_ignored_upper_bands[ch_index];
}
/* read the reference energy */
// test for read past end of fill element
if (seData->asDNSInfoStruct[ch_index].iWindowSequence == 2)
{
num_ref_energy_bits_to_read = SE_REF_ENERG_BITS_SHORT;
}
else
{
num_ref_energy_bits_to_read = SE_REF_ENERG_BITS_LONG;
}
if (readPastEndOfFillElement(cnt,num_bits_used,num_ref_energy_bits_to_read))
{
seData->iDolbyBitStreamWarning = 242;
return ((cnt*8) - num_bits_used);
}
get_bits_return_buffer = poBitStream->Get(num_ref_energy_bits_to_read);
num_bits_used += num_ref_energy_bits_to_read;
seData->delta_power_values[ch_index][grp_index][0] = get_bits_return_buffer;
/* read (num_se_bands[ch_index] - 1) Huffman encoded power values from the bitstream
(we've already read the first, absolute value from the file. */
for(i=0;i<seData->num_se_bands[ch_index]-1;i++)
{
powerval_index = decodeHuffCw(
SE_power_resolution_table[seData->asDNSInfoStruct[ch_index].iWindowSequence]
[seData->iSEPowerResolution].cwLengthLookupTable,
poBitStream,
cnt,
num_bits_used);
// check to see if decodeHuffCw wanted to read beyond the end of the Fill element
if (powerval_index < 0)
{
seData->iDolbyBitStreamWarning = 242;
return ((cnt*8) - (-powerval_index)); // -powerval_index is the number of bits already read by decodeHuffCw
}
seData->delta_power_values[ch_index][grp_index][i+1] =
(SE_power_resolution_table[seData->asDNSInfoStruct[ch_index].iWindowSequence]
[seData->iSEPowerResolution].cwValueLookupTable)
[powerval_index].cw;
num_bits_used +=
(SE_power_resolution_table[seData->asDNSInfoStruct[ch_index].iWindowSequence]
[seData->iSEPowerResolution].cwValueLookupTable)
[powerval_index].len;
}
} /* for (grp...) */
} /* for ch_index */
/* calculate number of bytes used and read fill bits to end on a multiple of 8 */
num_leftover_bits = num_bits_used % 8;
if (num_leftover_bits != 0)
{
/* debug: at this point, byte_align() could be called
in lieu of the next two lines of code. If byte_align is called,
it should return the number 8 - leftover_bits */
// test for read past end of fill element
if (readPastEndOfFillElement(cnt,num_bits_used,8 - num_leftover_bits))
{
seData->iDolbyBitStreamWarning = 242;
return ((cnt*8) - num_bits_used);
}
get_bits_return_buffer = poBitStream->Get(8 - num_leftover_bits);
num_bits_used += (8 - num_leftover_bits);
if (get_bits_return_buffer != 0)
{
/* 243 SE Bitstream synchronization error.*/
seData->iDolbyBitStreamWarning = 243;
return ((cnt*8) - num_bits_used);
}
}
/* at this point, n should be an exact integer, since we're at an even byte boundary */
n = (num_bits_used / 8);
/* At this point, there might be extra "pad bytes" in the SE data stream. This might
occur if the encoder found that it needed to "purge" some bits from the bit resevoir by including
pad (all zero) bytes in the current FILL element after the SE data. The encoder might have chosen to
do this if it found that the number of bits it wanted to purge was greater than the number of bits needed
to transmit the SE bitstream.
In this case, just read out the pad bytes until n = cnt. */
while(n < cnt)
{
// test for read past end of fill element
if (readPastEndOfFillElement(cnt,num_bits_used,8))
{
seData->iDolbyBitStreamWarning = 242;
return ((cnt*8) - num_bits_used);
}
get_bits_return_buffer = poBitStream->Get(8);
num_bits_used += 8;
if (get_bits_return_buffer != 0)
{
/* 243 SE Bitstream synchronization error.*/
seData->iDolbyBitStreamWarning = 243;
return ((cnt*8) - num_bits_used);
}
n += 1;
}
/* now, a sanity check: make sure we've read the correct number of bytes from the bitstream! */
if (n != cnt)
{
// Dolby SEv1.0: number of bytes read from bitstream != number of bytes in extension payload!
seData->iDolbyBitStreamWarning = 149;
return ((cnt*8) - num_bits_used);
}
// return the number of *bits* left in the payload, after reading all of the SE data.
// if there are no more payload bits, then the return value should be zero.
return (8*(cnt-n));
}
void spectralExtend(float* pfData,
int iCopyStart,
int iCopyStop,
int iSfm,
int iBandCount,
int* piBands,
int* piDeltaPowerValues,
float fDamp,
int iHBlockSize,
int iWnd,
int iSEPowerResolution,
int iPreviousWnd,
float* avgCopyEnergies)
{
/* SE declarations */
int iBandCounter;
int iCounter;
int iCopyPtr;
int iDestPtr;
int iDestPtrThisBand;
float fOneOverHBlockSize = 1.0f / (float) iHBlockSize;
float fCopyEnergy, fDestEnergy;
float fSFM;
float fNoiseRatio;
float fPhase;
float fScale0, fScale1, fNoise[2048], fAlpha[SE_NSHAPE_ORDER];
int iNoiseOffset;
/* additional declarations */
int iCopyWidth;
static int piWeights[MAX_NUM_POWER_VALUES];
static unsigned char uchIsOddFrame;
static int iFunctionInitialized = 0;
#ifdef DEBUG_PRINT_BUFFER_MODEL
// print out buffer model
static int already_printed_out_buffer_model = 0;
#endif
if (!iFunctionInitialized)
{
uchIsOddFrame = 0;
iFunctionInitialized = 1;
}
/* Compute some preliminaries */
iCopyWidth = iCopyStop - iCopyStart;
noiseGen(fNoise, ((iWnd == 2) ? 256 : 2048));
/* Time-Shape the noise prior to injection into extension */
computeLPC(pfData, SE_NSHAPE_ORDER, iCopyStart, iCopyStop, fAlpha);
synthesisFilter(fNoise, fAlpha, fDamp, ((iWnd == 2) ? 256 : 2048));
piWeights[0] = piDeltaPowerValues[0] - 32;
for (iBandCounter=1;iBandCounter<iBandCount;iBandCounter++)
{
piWeights[iBandCounter] = piDeltaPowerValues[iBandCounter] + piWeights[iBandCounter-1];
}
/* Compute how much noise to use */
fSFM = (float) iSfm;
fSFM /= ((iWnd == 2) ? ((1 << SE_SPECT_FLAT_BITS_SHORT) - 1) : ((1 << SE_SPECT_FLAT_BITS_LONG) - 1));
iNoiseOffset = (int) ((fSFM-0.15)*(float)iHBlockSize);
/* Create Noise records for use later */
#ifdef NEW_BUFFER_MODEL
iCopyPtr = iCopyStart + (iCopyStop - iCopyStart) % ((iWnd == 2) ? 2 : 16);
#else
iCopyPtr = iCopyStart;
#endif
iDestPtr = iCopyStop;
/* Do Spectral Replication: */
for(iBandCounter=0;iBandCounter<iBandCount;iBandCounter++)
{
fCopyEnergy=0.f;
fDestEnergy=decompressSEWeights(piWeights[iBandCounter],iSEPowerResolution);
#ifdef NEW_BUFFER_MODEL
// new buffer model for longs
// if we don't have enough continuous region in the baseband
// copy region, then we need to reset the copy pointer.
// 1) start the pointer at iCopyStart, which is 96 for
// long blocks and 12 for short blocks.
// N.B. that this setting must be done by the caller of spectralExtend()
// 2) we need to add to iCopyPtr the number of bins which will bring:
// a) for short blocks: the distance between iCopyPtr and iDestPtr
// to an EVEN number. By doing this, we can avoid having to deal with
// phase flipping issues. This additional "offset" is equal to (iDestPtr-iCopyStart) % 2
// b) for non short blocks: the distance between iCopyPtr and iDestPtr
// to an exact multiple of 16. 16 is chosen because it is divisible by 8 - in this manner,
// we can exactly match tones found in long block bins to short block bins. We also
// incorporate another factor of 2 here (2*8=16) so that the copying is done on boundaries
// of 2 short block bins. By doing this, we can avoid having to copy short block information
// an odd number of short block bins, and thus avoid a phase flip.
// new buffer model for longs
if (iCopyPtr + piBands[iBandCounter] > iCopyStop)
{
iCopyPtr = iCopyStart + (iDestPtr-iCopyStart) % ((iWnd == 2) ? 2 : 16);
}
#else
// old buffer model for longs
if (iCopyPtr + piBands[iBandCounter] > iCopyStop)
{
iCopyPtr = iCopyStart;
if ((iDestPtr-iCopyPtr)%2)
{
iCopyPtr++;
}
}
#endif
iDestPtrThisBand = iDestPtr; /* Save initial value for next piBand loop */
/* First Copy up the data and compute the copied energy: */
// replicate spectrum
for(iCounter=0;iCounter<piBands[iBandCounter];iCounter++)
{
float fTemp;
fTemp=pfData[iCopyPtr];
// fCopyEnergy+=(fTemp*fTemp);
/* Work out phase issues: */
if(uchIsOddFrame){
if((iDestPtr-iCopyPtr)%2) fPhase=-1.0;
else fPhase=1.0;
}
else fPhase=1.0;
pfData[iDestPtr]=fPhase*fTemp;
#ifdef DEBUG_PRINT_BUFFER_MODEL
//print out buffer model
if (iWnd == 2 &&
((already_printed_out_buffer_model == 0) || (already_printed_out_buffer_model == 1)) )
{
printf("%d %d\n",iDestPtr,iCopyPtr);
already_printed_out_buffer_model = 1;
}
#endif
iCopyPtr++;
iDestPtr++;
if (iCopyPtr >= iCopyStop)
{
iCopyPtr = iCopyStart + (iDestPtr-iCopyStart) % ((iWnd == 2) ? 2 : 16);
}
}
// /* Compute average energy for the band. */
// fCopyEnergy/=(float)piBands[iBandCounter];
// Even though average energies have already been computed, don't divide by zero
fCopyEnergy = avgCopyEnergies[iBandCounter];
if(fCopyEnergy==0.0f) fCopyEnergy=1.0f;
fScale0 = (float) sqrt(fDestEnergy / fCopyEnergy);
fScale1 = (float) sqrt(fDestEnergy);
iDestPtr = iDestPtrThisBand;
for(iCounter=0;iCounter<piBands[iBandCounter];iCounter++)
{
float fTemp;
if (iDestPtr-iNoiseOffset <= iHBlockSize)
{
fNoiseRatio=((float)(iDestPtr-iNoiseOffset))*fOneOverHBlockSize;
}
else
{
fNoiseRatio = 1.;
}
// legacy kludge: originally, this if statement read
// if (iWnd == 3)... We'd like to remove this if statement, and control noise
// inejction for shortblocks is handled directly by setting encoder parameters. However, we
// have content out there where shortblocks are disabled swhich is correctly decoded
// when the following statement reads (iWnd == 3). Thus, we have decided to fix the problem
// by adding a state variable which contains the previous window.
if (iWnd == 3 && iPreviousWnd != 2)
{
fNoiseRatio = (fNoiseRatio<0.08f)?fNoiseRatio:0.08f;
}
fNoiseRatio=(fNoiseRatio>0.0f)?fNoiseRatio:0.0f;
pfData[iDestPtr] *= (fScale0 * (1.0f - fNoiseRatio));
pfData[iDestPtr] += (fScale1 * fNoise[iDestPtr] * fNoiseRatio);
fTemp = 2.0f * fNoiseRatio;
pfData[iDestPtr] /= (float) sqrt(1.0f - fTemp + fTemp * fNoiseRatio);
iDestPtr++;
}
}
for(;iDestPtr<iHBlockSize;iDestPtr++)
{
pfData[iDestPtr] = 0.0f;
}
uchIsOddFrame^=1;
#ifdef DEBUG_PRINT_BUFFER_MODEL
if (already_printed_out_buffer_model == 1)
{
already_printed_out_buffer_model = 2;
}
#endif
}