*/
/**
- * @file libavcodec/wmaprodec.c
+ * @file
* @brief wmapro decoder implementation
* Wmapro is an MDCT based codec comparable to wma standard or AAC.
* The decoding therefore consists of the following steps:
int* scale_factors; ///< pointer to the scale factor values used for decoding
uint8_t table_idx; ///< index in sf_offsets for the scale factor reference block
float* coeffs; ///< pointer to the subframe decode buffer
- DECLARE_ALIGNED_16(float, out[WMAPRO_BLOCK_MAX_SIZE + WMAPRO_BLOCK_MAX_SIZE / 2]); ///< output buffer
+ DECLARE_ALIGNED(16, float, out)[WMAPRO_BLOCK_MAX_SIZE + WMAPRO_BLOCK_MAX_SIZE / 2]; ///< output buffer
} WMAProChannelCtx;
/**
FF_INPUT_BUFFER_PADDING_SIZE];///< compressed frame data
PutBitContext pb; ///< context for filling the frame_data buffer
FFTContext mdct_ctx[WMAPRO_BLOCK_SIZES]; ///< MDCT context per block size
- DECLARE_ALIGNED_16(float, tmp[WMAPRO_BLOCK_MAX_SIZE]); ///< IMDCT output buffer
+ DECLARE_ALIGNED(16, float, tmp)[WMAPRO_BLOCK_MAX_SIZE]; ///< IMDCT output buffer
float* windows[WMAPRO_BLOCK_SIZES]; ///< windows for the different block sizes
/* frame size dependent frame information (set during initialization) */
}
}
- if (s->num_channels < 0 || s->num_channels > WMAPRO_MAX_CHANNELS) {
- av_log_ask_for_sample(avctx, "invalid number of channels\n");
- return AVERROR_NOTSUPP;
+ if (s->num_channels < 0) {
+ av_log(avctx, AV_LOG_ERROR, "invalid number of channels %d\n", s->num_channels);
+ return AVERROR_INVALIDDATA;
+ } else if (s->num_channels > WMAPRO_MAX_CHANNELS) {
+ av_log_ask_for_sample(avctx, "unsupported number of channels\n");
+ return AVERROR_PATCHWELCOME;
}
INIT_VLC_STATIC(&sf_vlc, SCALEVLCBITS, HUFF_SCALE_SIZE,
/** init MDCT windows: simple sinus window */
for (i = 0; i < WMAPRO_BLOCK_SIZES; i++) {
- const int n = 1 << (WMAPRO_BLOCK_MAX_BITS - i);
const int win_idx = WMAPRO_BLOCK_MAX_BITS - i;
- ff_sine_window_init(ff_sine_windows[win_idx], n);
+ ff_init_ff_sine_windows(win_idx);
s->windows[WMAPRO_BLOCK_SIZES - i - 1] = ff_sine_windows[win_idx];
}
*/
static int decode_coeffs(WMAProDecodeCtx *s, int c)
{
+ /* Integers 0..15 as single-precision floats. The table saves a
+ costly int to float conversion, and storing the values as
+ integers allows fast sign-flipping. */
+ static const int fval_tab[16] = {
+ 0x00000000, 0x3f800000, 0x40000000, 0x40400000,
+ 0x40800000, 0x40a00000, 0x40c00000, 0x40e00000,
+ 0x41000000, 0x41100000, 0x41200000, 0x41300000,
+ 0x41400000, 0x41500000, 0x41600000, 0x41700000,
+ };
int vlctable;
VLC* vlc;
WMAProChannelCtx* ci = &s->channel[c];
for (i = 0; i < 4; i += 2) {
idx = get_vlc2(&s->gb, vec2_vlc.table, VLCBITS, VEC2MAXDEPTH);
if (idx == HUFF_VEC2_SIZE - 1) {
- vals[i] = get_vlc2(&s->gb, vec1_vlc.table, VLCBITS, VEC1MAXDEPTH);
- if (vals[i] == HUFF_VEC1_SIZE - 1)
- vals[i] += ff_wma_get_large_val(&s->gb);
- vals[i+1] = get_vlc2(&s->gb, vec1_vlc.table, VLCBITS, VEC1MAXDEPTH);
- if (vals[i+1] == HUFF_VEC1_SIZE - 1)
- vals[i+1] += ff_wma_get_large_val(&s->gb);
+ int v0, v1;
+ v0 = get_vlc2(&s->gb, vec1_vlc.table, VLCBITS, VEC1MAXDEPTH);
+ if (v0 == HUFF_VEC1_SIZE - 1)
+ v0 += ff_wma_get_large_val(&s->gb);
+ v1 = get_vlc2(&s->gb, vec1_vlc.table, VLCBITS, VEC1MAXDEPTH);
+ if (v1 == HUFF_VEC1_SIZE - 1)
+ v1 += ff_wma_get_large_val(&s->gb);
+ ((float*)vals)[i ] = v0;
+ ((float*)vals)[i+1] = v1;
} else {
- vals[i] = symbol_to_vec2[idx] >> 4;
- vals[i+1] = symbol_to_vec2[idx] & 0xF;
+ vals[i] = fval_tab[symbol_to_vec2[idx] >> 4 ];
+ vals[i+1] = fval_tab[symbol_to_vec2[idx] & 0xF];
}
}
} else {
- vals[0] = symbol_to_vec4[idx] >> 12;
- vals[1] = (symbol_to_vec4[idx] >> 8) & 0xF;
- vals[2] = (symbol_to_vec4[idx] >> 4) & 0xF;
- vals[3] = symbol_to_vec4[idx] & 0xF;
+ vals[0] = fval_tab[ symbol_to_vec4[idx] >> 12 ];
+ vals[1] = fval_tab[(symbol_to_vec4[idx] >> 8) & 0xF];
+ vals[2] = fval_tab[(symbol_to_vec4[idx] >> 4) & 0xF];
+ vals[3] = fval_tab[ symbol_to_vec4[idx] & 0xF];
}
/** decode sign */
for (i = 0; i < 4; i++) {
if (vals[i]) {
int sign = get_bits1(&s->gb) - 1;
- ci->coeffs[cur_coeff] = (vals[i] ^ sign) - sign;
+ *(uint32_t*)&ci->coeffs[cur_coeff] = vals[i] ^ sign<<31;
num_zeros = 0;
} else {
ci->coeffs[cur_coeff] = 0;
/** interleave samples and write them to the output buffer */
for (i = 0; i < s->num_channels; i++) {
- float* ptr;
+ float* ptr = s->samples + i;
int incr = s->num_channels;
float* iptr = s->channel[i].out;
- int x;
-
- ptr = s->samples + i;
+ float* iend = iptr + s->samples_per_frame;
- for (x = 0; x < s->samples_per_frame; x++) {
- *ptr = av_clipf(*iptr++, -1.0, 32767.0 / 32768.0);
+ // FIXME should create/use a DSP function here
+ while (iptr < iend) {
+ *ptr = *iptr++;
ptr += incr;
}
*/
AVCodec wmapro_decoder = {
"wmapro",
- CODEC_TYPE_AUDIO,
+ AVMEDIA_TYPE_AUDIO,
CODEC_ID_WMAPRO,
sizeof(WMAProDecodeCtx),
decode_init,