/* * WMA compatible decoder * * Extracted 2009 from the mplayer source code 2009-02-10. * * Copyright (c) 2002 The FFmpeg Project * * Licensed under the GNU Lesser General Public License, see file COPYING.LIB. */ /** \file wmadec_filter.c paraslash's WMA decoder. */ /* * This decoder handles Microsoft Windows Media Audio data version 2. */ #include #include "para.h" #include "error.h" #include "list.h" #include "string.h" #include "sched.h" #include "buffer_tree.h" #include "filter.h" #include "portable_io.h" #include "bitstream.h" #include "imdct.h" #include "wma.h" #include "wmadata.h" /* size of blocks */ #define BLOCK_MIN_BITS 7 #define BLOCK_MAX_BITS 11 #define BLOCK_MAX_SIZE (1 << BLOCK_MAX_BITS) #define BLOCK_NB_SIZES (BLOCK_MAX_BITS - BLOCK_MIN_BITS + 1) /* XXX: is it a suitable value ? */ #define MAX_CODED_SUPERFRAME_SIZE 16384 #define MAX_CHANNELS 2 #define LSP_POW_BITS 7 struct private_wmadec_data { /** Information contained in the audio file header. */ struct asf_header_info ahi; struct getbit_context gb; /** Depends on number of the bits per second and the frame length. */ int byte_offset_bits; /** Only used if ahi->use_exp_vlc is true. */ struct vlc exp_vlc; uint16_t exponent_bands[BLOCK_NB_SIZES][25]; /** The index of the first coef in high band. */ int high_band_start[BLOCK_NB_SIZES]; /** Maximal number of coded coefficients. */ int coefs_end[BLOCK_NB_SIZES]; /* there are two possible tables for spectral coefficients */ struct vlc coef_vlc[2]; uint16_t *run_table[2]; uint16_t *level_table[2]; /** Frame length in samples. */ int frame_len; /** log2 of frame_len. */ int frame_len_bits; /** Number of block sizes, one if !ahi->use_variable_block_len. */ int nb_block_sizes; /* Whether to update block lengths from getbit context. */ bool reset_block_lengths; /** log2 of current block length. */ int block_len_bits; /** log2 of next block length. */ int next_block_len_bits; /** log2 of previous block length. */ int prev_block_len_bits; /** Block length in samples. */ int block_len; /** Current position in frame. */ int block_pos; /** True if channel is coded. */ uint8_t channel_coded[MAX_CHANNELS]; /** log2 ratio frame/exp. length. */ int exponents_bsize[MAX_CHANNELS]; float exponents[MAX_CHANNELS][BLOCK_MAX_SIZE]; float max_exponent[MAX_CHANNELS]; int16_t coefs1[MAX_CHANNELS][BLOCK_MAX_SIZE]; float coefs[MAX_CHANNELS][BLOCK_MAX_SIZE]; float output[BLOCK_MAX_SIZE * 2]; struct mdct_context *mdct_ctx[BLOCK_NB_SIZES]; float *windows[BLOCK_NB_SIZES]; /** Output buffer for one frame and the last for IMDCT windowing. */ float frame_out[MAX_CHANNELS][BLOCK_MAX_SIZE * 2]; /** Last frame info. */ uint8_t last_superframe[MAX_CODED_SUPERFRAME_SIZE + 4]; /* padding added */ int last_bitoffset; int last_superframe_len; /* lsp_to_curve tables */ float lsp_cos_table[BLOCK_MAX_SIZE]; float lsp_pow_e_table[256]; float lsp_pow_m_table1[(1 << LSP_POW_BITS)]; float lsp_pow_m_table2[(1 << LSP_POW_BITS)]; }; #define EXPVLCBITS 8 #define VLCBITS 9 /** \cond sine_windows */ #define SINE_WINDOW(x) static float sine_ ## x[x] __a_aligned(16) SINE_WINDOW(128); SINE_WINDOW(256); SINE_WINDOW(512); SINE_WINDOW(1024); SINE_WINDOW(2048); SINE_WINDOW(4096); static float *sine_windows[6] = { sine_128, sine_256, sine_512, sine_1024, sine_2048, sine_4096 }; /** \endcond sine_windows */ /* Generate a sine window. */ static void sine_window_init(float *window, int n) { int i; for (i = 0; i < n; i++) window[i] = sinf((i + 0.5) * (M_PI / (2.0 * n))); } static void init_coef_vlc(struct private_wmadec_data *pwd, int sidx, int didx) { const struct coef_vlc_table *src = coef_vlcs + sidx; struct vlc *dst = pwd->coef_vlc + didx; int i, l, j, k, level, n = src->n; init_vlc(dst, VLCBITS, n, src->huffbits, src->huffcodes, 4); pwd->run_table[didx] = arr_alloc(n, sizeof(uint16_t)); pwd->level_table[didx] = arr_alloc(n, sizeof(uint16_t)); i = 2; level = 1; k = 0; while (i < n) { l = src->levels[k++]; for (j = 0; j < l; j++) { pwd->run_table[didx][i] = j; pwd->level_table[didx][i] = level; i++; } level++; } } /* compute the scale factor band sizes for each MDCT block size */ static void compute_scale_factor_band_sizes(struct private_wmadec_data *pwd, float high_freq) { struct asf_header_info *ahi = &pwd->ahi; int a, b, pos, lpos, k, block_len, i, j, n; const uint8_t *table; for (k = 0; k < pwd->nb_block_sizes; k++) { int exponent_size; block_len = pwd->frame_len >> k; table = NULL; a = pwd->frame_len_bits - BLOCK_MIN_BITS - k; if (a < 3) { if (ahi->sample_rate >= 44100) table = exponent_band_44100[a]; else if (ahi->sample_rate >= 32000) table = exponent_band_32000[a]; else if (ahi->sample_rate >= 22050) table = exponent_band_22050[a]; } if (table) { n = *table++; for (i = 0; i < n; i++) pwd->exponent_bands[k][i] = table[i]; exponent_size = n; } else { j = 0; lpos = 0; for (i = 0; i < 25; i++) { a = wma_critical_freqs[i]; b = ahi->sample_rate; pos = ((block_len * 2 * a) + (b << 1)) / (4 * b); pos <<= 2; if (pos > block_len) pos = block_len; if (pos > lpos) pwd->exponent_bands[k][j++] = pos - lpos; if (pos >= block_len) break; lpos = pos; } exponent_size = j; } /* max number of coefs */ pwd->coefs_end[k] = (pwd->frame_len - ((pwd->frame_len * 9) / 100)) >> k; /* high freq computation */ pwd->high_band_start[k] = (int) ((block_len * 2 * high_freq) / ahi->sample_rate + 0.5); n = exponent_size; pos = 0; for (i = 0; i < n; i++) pos += pwd->exponent_bands[k][i]; } } static int wma_init(struct private_wmadec_data *pwd) { int i; float bps1, high_freq; volatile float bps; int sample_rate1; int coef_vlc_table; struct asf_header_info *ahi = &pwd->ahi; int flags2 = ahi->flags2; if (ahi->sample_rate <= 0 || ahi->sample_rate > 50000 || ahi->channels <= 0 || ahi->channels > 8 || ahi->bit_rate <= 0) return -E_WMA_BAD_PARAMS; /* compute MDCT block size */ if (ahi->sample_rate <= 16000) pwd->frame_len_bits = 9; else if (ahi->sample_rate <= 22050) pwd->frame_len_bits = 10; else pwd->frame_len_bits = 11; pwd->frame_len = 1 << pwd->frame_len_bits; if (pwd->ahi.use_variable_block_len) { int nb_max, nb; nb = ((flags2 >> 3) & 3) + 1; if ((ahi->bit_rate / ahi->channels) >= 32000) nb += 2; nb_max = pwd->frame_len_bits - BLOCK_MIN_BITS; if (nb > nb_max) nb = nb_max; pwd->nb_block_sizes = nb + 1; } else pwd->nb_block_sizes = 1; /* init rate dependent parameters */ high_freq = ahi->sample_rate * 0.5; /* wma2 rates are normalized */ sample_rate1 = ahi->sample_rate; if (sample_rate1 >= 44100) sample_rate1 = 44100; else if (sample_rate1 >= 22050) sample_rate1 = 22050; else if (sample_rate1 >= 16000) sample_rate1 = 16000; else if (sample_rate1 >= 11025) sample_rate1 = 11025; else if (sample_rate1 >= 8000) sample_rate1 = 8000; bps = (float) ahi->bit_rate / (float) (ahi->channels * ahi->sample_rate); pwd->byte_offset_bits = wma_log2((int) (bps * pwd->frame_len / 8.0 + 0.5)) + 2; /* Adjust bps and compute high frequency value. */ bps1 = bps; if (ahi->channels == 2) bps1 = bps * 1.6; if (sample_rate1 == 44100) { if (bps1 < 0.61) high_freq = high_freq * 0.4; } else if (sample_rate1 == 22050) { if (bps1 < 1.16) { if (bps1 >= 0.72) high_freq = high_freq * 0.7; else high_freq = high_freq * 0.6; } } else if (sample_rate1 == 16000) { if (bps > 0.5) high_freq = high_freq * 0.5; else high_freq = high_freq * 0.3; } else if (sample_rate1 == 11025) high_freq = high_freq * 0.7; else if (sample_rate1 == 8000) { if (bps <= 0.625) high_freq = high_freq * 0.5; else if (bps <= 0.75) high_freq = high_freq * 0.65; } else { if (bps >= 0.8) high_freq = high_freq * 0.75; else if (bps >= 0.6) high_freq = high_freq * 0.6; else high_freq = high_freq * 0.5; } PARA_INFO_LOG("channels=%u sample_rate=%u " "bitrate=%u block_align=%d\n", ahi->channels, ahi->sample_rate, ahi->bit_rate, ahi->block_align); PARA_INFO_LOG("frame_len=%d, bps=%f bps1=%f " "high_freq=%f bitoffset=%d\n", pwd->frame_len, bps, bps1, high_freq, pwd->byte_offset_bits); PARA_INFO_LOG("use_exp_vlc=%d nb_block_sizes=%d\n", pwd->ahi.use_exp_vlc, pwd->nb_block_sizes); compute_scale_factor_band_sizes(pwd, high_freq); /* init MDCT windows : simple sinus window */ for (i = 0; i < pwd->nb_block_sizes; i++) { int n; n = 1 << (pwd->frame_len_bits - i); sine_window_init(sine_windows[pwd->frame_len_bits - i - 7], n); pwd->windows[i] = sine_windows[pwd->frame_len_bits - i - 7]; } pwd->reset_block_lengths = true; /* choose the VLC tables for the coefficients */ coef_vlc_table = 4; if (ahi->sample_rate >= 32000) { if (bps1 < 0.72) coef_vlc_table = 0; else if (bps1 < 1.16) coef_vlc_table = 2; } init_coef_vlc(pwd, coef_vlc_table, 0); init_coef_vlc(pwd, coef_vlc_table + 1, 1); return 0; } static void wma_lsp_to_curve_init(struct private_wmadec_data *pwd) { float wdel, a, b; int i, e, m; wdel = M_PI / pwd->frame_len; for (i = 0; i < pwd->frame_len; i++) pwd->lsp_cos_table[i] = 2.0f * cos(wdel * i); /* tables for x^-0.25 computation */ for (i = 0; i < 256; i++) { e = i - 126; pwd->lsp_pow_e_table[i] = pow(2.0, e * -0.25); } /* These two tables are needed to avoid two operations in pow_m1_4. */ b = 1.0; for (i = (1 << LSP_POW_BITS) - 1; i >= 0; i--) { m = (1 << LSP_POW_BITS) + i; a = (float) m *(0.5 / (1 << LSP_POW_BITS)); a = pow(a, -0.25); pwd->lsp_pow_m_table1[i] = 2 * a - b; pwd->lsp_pow_m_table2[i] = b - a; b = a; } } static int wma_decode_init(char *initial_buf, int len, struct private_wmadec_data **result) { struct private_wmadec_data *pwd; int ret, i; PARA_NOTICE_LOG("initial buf: %d bytes\n", len); pwd = zalloc(sizeof(*pwd)); ret = read_asf_header(initial_buf, len, &pwd->ahi); if (ret <= 0) { free(pwd); return ret; } ret = wma_init(pwd); if (ret < 0) return ret; /* init MDCT */ for (i = 0; i < pwd->nb_block_sizes; i++) { ret = imdct_init(pwd->frame_len_bits - i + 1, &pwd->mdct_ctx[i]); if (ret < 0) return ret; } if (pwd->ahi.use_exp_vlc) { PARA_INFO_LOG("using exp_vlc\n"); init_vlc(&pwd->exp_vlc, EXPVLCBITS, sizeof(wma_scale_huffbits), wma_scale_huffbits, wma_scale_huffcodes, 4); } else { PARA_INFO_LOG("using curve\n"); wma_lsp_to_curve_init(pwd); } *result = pwd; return pwd->ahi.header_len; } /** * compute x^-0.25 with an exponent and mantissa table. We use linear * interpolation to reduce the mantissa table size at a small speed * expense (linear interpolation approximately doubles the number of * bits of precision). */ static inline float pow_m1_4(struct private_wmadec_data *pwd, float x) { union { float f; unsigned int v; } u, t; unsigned int e, m; float a, b; u.f = x; e = u.v >> 23; m = (u.v >> (23 - LSP_POW_BITS)) & ((1 << LSP_POW_BITS) - 1); /* build interpolation scale: 1 <= t < 2. */ t.v = ((u.v << LSP_POW_BITS) & ((1 << 23) - 1)) | (127 << 23); a = pwd->lsp_pow_m_table1[m]; b = pwd->lsp_pow_m_table2[m]; return pwd->lsp_pow_e_table[e] * (a + b * t.f); } static void wma_lsp_to_curve(struct private_wmadec_data *pwd, float *out, float *val_max_ptr, int n, float *lsp) { int i, j; float p, q, w, v, val_max; val_max = 0; for (i = 0; i < n; i++) { p = 0.5f; q = 0.5f; w = pwd->lsp_cos_table[i]; for (j = 1; j < NB_LSP_COEFS; j += 2) { q *= w - lsp[j - 1]; p *= w - lsp[j]; } p *= p * (2.0f - w); q *= q * (2.0f + w); v = p + q; v = pow_m1_4(pwd, v); if (v > val_max) val_max = v; out[i] = v; } *val_max_ptr = val_max; } /* Decode exponents coded with LSP coefficients (same idea as Vorbis). */ static void decode_exp_lsp(struct private_wmadec_data *pwd, int ch) { float lsp_coefs[NB_LSP_COEFS]; int val, i; for (i = 0; i < NB_LSP_COEFS; i++) { if (i == 0 || i >= 8) val = get_bits(&pwd->gb, 3); else val = get_bits(&pwd->gb, 4); lsp_coefs[i] = wma_lsp_codebook[i][val]; } wma_lsp_to_curve(pwd, pwd->exponents[ch], &pwd->max_exponent[ch], pwd->block_len, lsp_coefs); } /* Decode exponents coded with VLC codes. */ static int decode_exp_vlc(struct private_wmadec_data *pwd, int ch) { int last_exp, n, code; const uint16_t *ptr, *band_ptr; float v, *q, max_scale, *q_end; band_ptr = pwd->exponent_bands[pwd->frame_len_bits - pwd->block_len_bits]; ptr = band_ptr; q = pwd->exponents[ch]; q_end = q + pwd->block_len; max_scale = 0; last_exp = 36; while (q < q_end) { code = get_vlc(&pwd->gb, &pwd->exp_vlc); if (code < 0) return code; /* NOTE: this offset is the same as MPEG4 AAC ! */ last_exp += code - 60; /* XXX: use a table */ v = pow(10, last_exp * (1.0 / 16.0)); if (v > max_scale) max_scale = v; n = *ptr++; do { *q++ = v; } while (--n); } pwd->max_exponent[ch] = max_scale; return 0; } /* compute src0 * src1 + src2 */ static inline void vector_mult_add(float *dst, const float *src0, const float *src1, const float *src2, int len) { int i; for (i = 0; i < len; i++) dst[i] = src0[i] * src1[i] + src2[i]; } static inline void vector_mult_reverse(float *dst, const float *src0, const float *src1, int len) { int i; src1 += len - 1; for (i = 0; i < len; i++) dst[i] = src0[i] * src1[-i]; } /** * Apply MDCT window and add into output. * * We ensure that when the windows overlap their squared sum * is always 1 (MDCT reconstruction rule). */ static void wma_window(struct private_wmadec_data *pwd, float *out) { float *in = pwd->output; int block_len, bsize, n; /* left part */ if (pwd->block_len_bits <= pwd->prev_block_len_bits) { block_len = pwd->block_len; bsize = pwd->frame_len_bits - pwd->block_len_bits; vector_mult_add(out, in, pwd->windows[bsize], out, block_len); } else { block_len = 1 << pwd->prev_block_len_bits; n = (pwd->block_len - block_len) / 2; bsize = pwd->frame_len_bits - pwd->prev_block_len_bits; vector_mult_add(out + n, in + n, pwd->windows[bsize], out + n, block_len); memcpy(out + n + block_len, in + n + block_len, n * sizeof(float)); } out += pwd->block_len; in += pwd->block_len; /* right part */ if (pwd->block_len_bits <= pwd->next_block_len_bits) { block_len = pwd->block_len; bsize = pwd->frame_len_bits - pwd->block_len_bits; vector_mult_reverse(out, in, pwd->windows[bsize], block_len); } else { block_len = 1 << pwd->next_block_len_bits; n = (pwd->block_len - block_len) / 2; bsize = pwd->frame_len_bits - pwd->next_block_len_bits; memcpy(out, in, n * sizeof(float)); vector_mult_reverse(out + n, in + n, pwd->windows[bsize], block_len); memset(out + n + block_len, 0, n * sizeof(float)); } } static int wma_total_gain_to_bits(int total_gain) { if (total_gain < 15) return 13; else if (total_gain < 32) return 12; else if (total_gain < 40) return 11; else if (total_gain < 45) return 10; else return 9; } 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; int i, n, esize; 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]; /* 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; } } /** * Returns 0 if OK, 1 if last block of frame, negative on uncorrectable * errors. */ static int wma_decode_block(struct private_wmadec_data *pwd) { int ret, n, v, ch, code, bsize; int coef_nb_bits, total_gain; int nb_coefs[MAX_CHANNELS]; bool ms_stereo = false; /* mid/side stereo mode */ /* compute current block length */ if (pwd->ahi.use_variable_block_len) { n = wma_log2(pwd->nb_block_sizes - 1) + 1; if (pwd->reset_block_lengths) { pwd->reset_block_lengths = false; v = get_bits(&pwd->gb, n); if (v >= pwd->nb_block_sizes) return -E_WMA_BLOCK_SIZE; pwd->prev_block_len_bits = pwd->frame_len_bits - v; v = get_bits(&pwd->gb, n); if (v >= pwd->nb_block_sizes) return -E_WMA_BLOCK_SIZE; pwd->block_len_bits = pwd->frame_len_bits - v; } else { /* update block lengths */ pwd->prev_block_len_bits = pwd->block_len_bits; pwd->block_len_bits = pwd->next_block_len_bits; } v = get_bits(&pwd->gb, n); if (v >= pwd->nb_block_sizes) return -E_WMA_BLOCK_SIZE; pwd->next_block_len_bits = pwd->frame_len_bits - v; } else { /* fixed block len */ pwd->next_block_len_bits = pwd->frame_len_bits; pwd->prev_block_len_bits = pwd->frame_len_bits; pwd->block_len_bits = pwd->frame_len_bits; } /* now check if the block length is coherent with the frame length */ pwd->block_len = 1 << pwd->block_len_bits; if ((pwd->block_pos + pwd->block_len) > pwd->frame_len) return -E_INCOHERENT_BLOCK_LEN; if (pwd->ahi.channels == 2) ms_stereo = get_bit(&pwd->gb); v = 0; for (ch = 0; ch < pwd->ahi.channels; ch++) { int a = get_bit(&pwd->gb); pwd->channel_coded[ch] = a; v |= a; } bsize = pwd->frame_len_bits - pwd->block_len_bits; /* if no channel coded, no need to go further */ /* XXX: fix potential framing problems */ if (!v) goto next; /* * Read total gain and extract corresponding number of bits for coef * escape coding. */ total_gain = 1; for (;;) { int a = get_bits(&pwd->gb, 7); total_gain += a; if (a != 127) break; } coef_nb_bits = wma_total_gain_to_bits(total_gain); /* compute number of coefficients */ n = pwd->coefs_end[bsize]; for (ch = 0; ch < pwd->ahi.channels; ch++) nb_coefs[ch] = n; /* exponents can be reused in short blocks. */ if ((pwd->block_len_bits == pwd->frame_len_bits) || get_bit(&pwd->gb)) { for (ch = 0; ch < pwd->ahi.channels; ch++) { if (pwd->channel_coded[ch]) { if (pwd->ahi.use_exp_vlc) { ret = decode_exp_vlc(pwd, ch); if (ret < 0) return ret; } else decode_exp_lsp(pwd, ch); pwd->exponents_bsize[ch] = bsize; } } } /* parse spectral coefficients : just RLE encoding */ for (ch = 0; ch < pwd->ahi.channels; ch++) { struct vlc *coef_vlc; int level, run, tindex; int16_t *ptr, *eptr; const uint16_t *level_table, *run_table; if (!pwd->channel_coded[ch]) continue; /* * special VLC tables are used for ms stereo because there is * potentially less energy there */ tindex = ch == 1 && ms_stereo; coef_vlc = &pwd->coef_vlc[tindex]; run_table = pwd->run_table[tindex]; level_table = pwd->level_table[tindex]; /* XXX: optimize */ ptr = &pwd->coefs1[ch][0]; eptr = ptr + nb_coefs[ch]; memset(ptr, 0, pwd->block_len * sizeof(int16_t)); for (;;) { code = get_vlc(&pwd->gb, coef_vlc); if (code < 0) return code; if (code == 1) /* EOB */ break; if (code == 0) { /* escape */ level = get_bits(&pwd->gb, coef_nb_bits); /* reading block_len_bits would be better */ run = get_bits(&pwd->gb, pwd->frame_len_bits); } else { /* normal code */ run = run_table[code]; level = level_table[code]; } if (!get_bit(&pwd->gb)) level = -level; ptr += run; if (ptr >= eptr) { PARA_ERROR_LOG("overflow in spectral RLE, ignoring\n"); break; } *ptr++ = level; if (ptr >= eptr) /* EOB can be omitted */ break; } } compute_mdct_coefficients(pwd, bsize, total_gain, nb_coefs); if (ms_stereo && pwd->channel_coded[1]) { float a, b; int i; /* * Nominal case for ms stereo: we do it before mdct. * * No need to optimize this case because it should almost never * happen. */ if (!pwd->channel_coded[0]) { PARA_NOTICE_LOG("rare ms-stereo\n"); memset(pwd->coefs[0], 0, sizeof(float) * pwd->block_len); pwd->channel_coded[0] = 1; } for (i = 0; i < pwd->block_len; i++) { a = pwd->coefs[0][i]; b = pwd->coefs[1][i]; pwd->coefs[0][i] = a + b; pwd->coefs[1][i] = a - b; } } next: for (ch = 0; ch < pwd->ahi.channels; ch++) { int n4, idx; n4 = pwd->block_len / 2; if (pwd->channel_coded[ch]) imdct(pwd->mdct_ctx[bsize], pwd->output, pwd->coefs[ch]); else if (!(ms_stereo && ch == 1)) memset(pwd->output, 0, sizeof(pwd->output)); /* multiply by the window and add in the frame */ idx = (pwd->frame_len / 2) + pwd->block_pos - n4; wma_window(pwd, &pwd->frame_out[ch][idx]); } /* update block number */ pwd->block_pos += pwd->block_len; if (pwd->block_pos >= pwd->frame_len) return 1; else return 0; } /* * Clip a signed integer value into the -32768,32767 range. * * \param a The value to clip. * * \return The clipped value. */ static inline int16_t av_clip_int16(int a) { if ((a + 32768) & ~65535) return (a >> 31) ^ 32767; else return a; } /* Decode a frame of frame_len samples. */ static int wma_decode_frame(struct private_wmadec_data *pwd, int16_t *samples) { int ret, i, ch; int16_t *ptr; float *iptr; /* read each block */ pwd->block_pos = 0; for (;;) { ret = wma_decode_block(pwd); if (ret < 0) return ret; if (ret) break; } /* convert frame to integer */ for (ch = 0; ch < pwd->ahi.channels; ch++) { ptr = samples + ch; iptr = pwd->frame_out[ch]; for (i = 0; i < pwd->frame_len; i++) { *ptr = av_clip_int16(lrintf(*iptr++)); ptr += pwd->ahi.channels; } /* prepare for next block */ memmove(&pwd->frame_out[ch][0], &pwd->frame_out[ch][pwd->frame_len], pwd->frame_len * sizeof(float)); } return 0; } static int wma_decode_superframe(struct private_wmadec_data *pwd, void *out, int *out_size, const uint8_t *in) { int ret, in_size = pwd->ahi.packet_size - WMA_FRAME_SKIP; int16_t *samples = out; init_get_bits(&pwd->gb, in, in_size); if (pwd->ahi.use_bit_reservoir) { int i, nb_frames, bit_offset, pos, len; uint8_t *q; /* read super frame header */ skip_bits(&pwd->gb, 4); /* super frame index */ nb_frames = get_bits(&pwd->gb, 4) - 1; // PARA_DEBUG_LOG("have %d frames\n", nb_frames); ret = -E_WMA_OUTPUT_SPACE; if ((nb_frames + 1) * pwd->ahi.channels * pwd->frame_len * sizeof(int16_t) > *out_size) goto fail; bit_offset = get_bits(&pwd->gb, pwd->byte_offset_bits + 3); if (pwd->last_superframe_len > 0) { /* add bit_offset bits to last frame */ ret = -E_WMA_BAD_SUPERFRAME; if ((pwd->last_superframe_len + ((bit_offset + 7) >> 3)) > MAX_CODED_SUPERFRAME_SIZE) goto fail; q = pwd->last_superframe + pwd->last_superframe_len; len = bit_offset; while (len > 7) { *q++ = get_bits(&pwd->gb, 8); len -= 8; } if (len > 0) *q++ = get_bits(&pwd->gb, len) << (8 - len); /* XXX: bit_offset bits into last frame */ init_get_bits(&pwd->gb, pwd->last_superframe, MAX_CODED_SUPERFRAME_SIZE); /* skip unused bits */ if (pwd->last_bitoffset > 0) skip_bits(&pwd->gb, pwd->last_bitoffset); /* * This frame is stored in the last superframe and in * the current one. */ ret = wma_decode_frame(pwd, samples); if (ret < 0) goto fail; samples += pwd->ahi.channels * pwd->frame_len; } /* read each frame starting from bit_offset */ pos = bit_offset + 4 + 4 + pwd->byte_offset_bits + 3; init_get_bits(&pwd->gb, in + (pos >> 3), (MAX_CODED_SUPERFRAME_SIZE - (pos >> 3))); len = pos & 7; if (len > 0) skip_bits(&pwd->gb, len); pwd->reset_block_lengths = true; for (i = 0; i < nb_frames; i++) { ret = wma_decode_frame(pwd, samples); if (ret < 0) goto fail; samples += pwd->ahi.channels * pwd->frame_len; } /* we copy the end of the frame in the last frame buffer */ pos = get_bits_count(&pwd->gb) + ((bit_offset + 4 + 4 + pwd->byte_offset_bits + 3) & ~7); pwd->last_bitoffset = pos & 7; pos >>= 3; len = in_size - pos; ret = -E_WMA_BAD_SUPERFRAME; if (len > MAX_CODED_SUPERFRAME_SIZE || len < 0) goto fail; pwd->last_superframe_len = len; memcpy(pwd->last_superframe, in + pos, len); } else { PARA_DEBUG_LOG("not using bit reservoir\n"); ret = -E_WMA_OUTPUT_SPACE; if (pwd->ahi.channels * pwd->frame_len * sizeof(int16_t) > *out_size) goto fail; /* single frame decode */ ret = wma_decode_frame(pwd, samples); if (ret < 0) goto fail; samples += pwd->ahi.channels * pwd->frame_len; } PARA_DEBUG_LOG("frame_len: %d, block_len: %d, outbytes: %d, eaten: %d\n", pwd->frame_len, pwd->block_len, (int)((int8_t *)samples - (int8_t *)out), pwd->ahi.block_align); *out_size = (int8_t *)samples - (int8_t *)out; return pwd->ahi.block_align; fail: /* reset the bit reservoir on errors */ pwd->last_superframe_len = 0; return ret; } static void wmadec_close(struct filter_node *fn) { struct private_wmadec_data *pwd = fn->private_data; int i; if (!pwd) return; for (i = 0; i < pwd->nb_block_sizes; i++) imdct_end(pwd->mdct_ctx[i]); if (pwd->ahi.use_exp_vlc) free_vlc(&pwd->exp_vlc); for (i = 0; i < 2; i++) { free_vlc(&pwd->coef_vlc[i]); free(pwd->run_table[i]); free(pwd->level_table[i]); } free(fn->private_data); fn->private_data = NULL; } static int wmadec_execute(const struct btr_node *btrn, const char *cmd, char **result) { struct filter_node *fn = btr_context(btrn); struct private_wmadec_data *pwd = fn->private_data; return decoder_execute(cmd, pwd->ahi.sample_rate, pwd->ahi.channels, result); } #define WMA_OUTPUT_BUFFER_SIZE (128 * 1024) static int wmadec_post_monitor(__a_unused struct sched *s, void *context) { struct filter_node *fn = context; int ret, converted, out_size; struct private_wmadec_data *pwd = fn->private_data; struct btr_node *btrn = fn->btrn; size_t len; char *in, *out; next_buffer: converted = 0; ret = btr_node_status(btrn, fn->min_iqs, BTR_NT_INTERNAL); if (ret < 0) goto err; if (ret == 0) return 0; btr_merge(btrn, fn->min_iqs); len = btr_next_buffer(btrn, &in); ret = -E_EOF; if (len < fn->min_iqs) goto err; if (!pwd) { ret = wma_decode_init(in, len, &pwd); if (ret < 0) goto err; if (ret == 0) { fn->min_iqs += 4096; goto next_buffer; } fn->min_iqs = 2 * pwd->ahi.packet_size; fn->private_data = pwd; converted = pwd->ahi.header_len; goto success; } fn->min_iqs = pwd->ahi.packet_size; if (fn->min_iqs > len) goto success; out_size = WMA_OUTPUT_BUFFER_SIZE; out = alloc(out_size); ret = wma_decode_superframe(pwd, out, &out_size, (uint8_t *)in + WMA_FRAME_SKIP); if (ret < 0) { free(out); goto err; } if (out_size > 0) { out = para_realloc(out, out_size); btr_add_output(out, out_size, btrn); } else free(out); converted += pwd->ahi.packet_size; success: btr_consume(btrn, converted); return 0; err: assert(ret < 0); btr_remove_node(&fn->btrn); return ret; } static void wmadec_open(struct filter_node *fn) { fn->private_data = NULL; fn->min_iqs = 4096; } /** \cond doxygen_ignore */ const struct filter lsg_filter_cmd_com_wmadec_user_data = { .open = wmadec_open, .close = wmadec_close, .execute = wmadec_execute, .pre_monitor = generic_filter_pre_monitor, .post_monitor = wmadec_post_monitor, }; /** \endcond */