+static int compute_high_band_values(struct private_wmadec_data *pwd,
+ int bsize, int nb_coefs[MAX_CHANNELS])
+{
+ int ch;
+
+ if (!pwd->use_noise_coding)
+ return 0;
+ for (ch = 0; ch < pwd->ahi.channels; ch++) {
+ int i, m, a;
+ if (!pwd->channel_coded[ch])
+ continue;
+ m = pwd->exponent_high_sizes[bsize];
+ for (i = 0; i < m; i++) {
+ a = get_bit(&pwd->gb);
+ pwd->high_band_coded[ch][i] = a;
+ if (!a)
+ continue;
+ nb_coefs[ch] -= pwd->exponent_high_bands[bsize][i];
+ }
+ }
+ for (ch = 0; ch < pwd->ahi.channels; ch++) {
+ int i, n, val;
+ if (!pwd->channel_coded[ch])
+ continue;
+ n = pwd->exponent_high_sizes[bsize];
+ val = (int)0x80000000;
+ for (i = 0; i < n; i++) {
+ if (!pwd->high_band_coded[ch][i])
+ continue;
+ if (val == (int)0x80000000)
+ val = get_bits(&pwd->gb, 7) - 19;
+ else {
+ int code = get_vlc(&pwd->gb,
+ pwd->hgain_vlc.table, HGAINVLCBITS,
+ HGAINMAX);
+ if (code < 0)
+ return code;
+ val += code - 18;
+ }
+ pwd->high_band_values[ch][i] = val;
+ }
+ }
+ return 1;
+}
+
+static void compute_mdct_coefficients(struct private_wmadec_data *pwd,
+ int bsize, int total_gain, int nb_coefs[MAX_CHANNELS])
+{
+ int ch;
+ float mdct_norm = 1.0 / (pwd->block_len / 2);
+
+ for (ch = 0; ch < pwd->ahi.channels; ch++) {
+ int16_t *coefs1;
+ float *coefs, *exponents, mult, mult1, noise;
+ int i, j, n, n1, last_high_band, esize;
+ float exp_power[HIGH_BAND_MAX_SIZE];
+
+ if (!pwd->channel_coded[ch])
+ continue;
+ coefs1 = pwd->coefs1[ch];
+ exponents = pwd->exponents[ch];
+ esize = pwd->exponents_bsize[ch];
+ mult = pow(10, total_gain * 0.05) / pwd->max_exponent[ch];
+ mult *= mdct_norm;
+ coefs = pwd->coefs[ch];
+ if (!pwd->use_noise_coding) {
+ /* XXX: optimize more */
+ n = nb_coefs[ch];
+ for (i = 0; i < n; i++)
+ *coefs++ = coefs1[i] *
+ exponents[i << bsize >> esize] * mult;
+ n = pwd->block_len - pwd->coefs_end[bsize];
+ for (i = 0; i < n; i++)
+ *coefs++ = 0.0;
+ continue;
+ }
+ mult1 = mult;
+ n1 = pwd->exponent_high_sizes[bsize];
+ /* compute power of high bands */
+ exponents = pwd->exponents[ch] +
+ (pwd->high_band_start[bsize] << bsize);
+ last_high_band = 0; /* avoid warning */
+ for (j = 0; j < n1; j++) {
+ n = pwd->exponent_high_bands[
+ pwd->frame_len_bits - pwd->block_len_bits][j];
+ if (pwd->high_band_coded[ch][j]) {
+ float e2, val;
+ e2 = 0;
+ for (i = 0; i < n; i++) {
+ val = exponents[i << bsize >> esize];
+ e2 += val * val;
+ }
+ exp_power[j] = e2 / n;
+ last_high_band = j;
+ }
+ exponents += n << bsize;
+ }
+ /* main freqs and high freqs */
+ exponents = pwd->exponents[ch];
+ for (j = -1; j < n1; j++) {
+ if (j < 0)
+ n = pwd->high_band_start[bsize];
+ else
+ n = pwd->exponent_high_bands[pwd->frame_len_bits
+ - pwd->block_len_bits][j];
+ if (j >= 0 && pwd->high_band_coded[ch][j]) {
+ /* use noise with specified power */
+ mult1 = sqrt(exp_power[j]
+ / exp_power[last_high_band]);
+ /* XXX: use a table */
+ mult1 = mult1 * pow(10,
+ pwd->high_band_values[ch][j] * 0.05);
+ mult1 /= (pwd->max_exponent[ch] * pwd->noise_mult);
+ mult1 *= mdct_norm;
+ for (i = 0; i < n; i++) {
+ noise = pwd->noise_table[pwd->noise_index];
+ pwd->noise_index = (pwd->noise_index + 1)
+ & (NOISE_TAB_SIZE - 1);
+ *coefs++ = noise * exponents[
+ i << bsize >> esize] * mult1;
+ }
+ exponents += n << bsize;
+ } else {
+ /* coded values + small noise */
+ for (i = 0; i < n; i++) {
+ noise = pwd->noise_table[pwd->noise_index];
+ pwd->noise_index = (pwd->noise_index + 1)
+ & (NOISE_TAB_SIZE - 1);
+ *coefs++ = ((*coefs1++) + noise) *
+ exponents[i << bsize >> esize]
+ * mult;
+ }
+ exponents += n << bsize;
+ }
+ }
+ /* very high freqs: noise */
+ n = pwd->block_len - pwd->coefs_end[bsize];
+ mult1 = mult * exponents[((-1 << bsize)) >> esize];
+ for (i = 0; i < n; i++) {
+ *coefs++ = pwd->noise_table[pwd->noise_index] * mult1;
+ pwd->noise_index = (pwd->noise_index + 1)
+ & (NOISE_TAB_SIZE - 1);
+ }
+ }
+}
+