]> rtime.felk.cvut.cz Git - frescor/ffmpeg.git/blobdiff - libavcodec/wmaprodec.c
WMA: extend exponent range to 95
[frescor/ffmpeg.git] / libavcodec / wmaprodec.c
index 2a45312ec0d5e5eac7c193136e1e2b839901b06c..cbc97d9c82aaf50c3ea41a969bcb4e0af472e8fd 100644 (file)
@@ -98,7 +98,7 @@
 #define WMAPRO_MAX_CHANNELS    8                             ///< max number of handled channels
 #define MAX_SUBFRAMES  32                                    ///< max number of subframes per channel
 #define MAX_BANDS      29                                    ///< max number of scale factor bands
-#define MAX_FRAMESIZE  16384                                 ///< maximum compressed frame size
+#define MAX_FRAMESIZE  32768                                 ///< maximum compressed frame size
 
 #define WMAPRO_BLOCK_MAX_BITS 12                                           ///< log2 of max block size
 #define WMAPRO_BLOCK_MAX_SIZE (1 << WMAPRO_BLOCK_MAX_BITS)                 ///< maximum block size
@@ -166,7 +166,7 @@ typedef struct WMAProDecodeCtx {
     uint8_t          frame_data[MAX_FRAMESIZE +
                       FF_INPUT_BUFFER_PADDING_SIZE];///< compressed frame data
     PutBitContext    pb;                            ///< context for filling the frame_data buffer
-    MDCTContext      mdct_ctx[WMAPRO_BLOCK_SIZES];  ///< MDCT context per block size
+    FFTContext       mdct_ctx[WMAPRO_BLOCK_SIZES];  ///< MDCT context per block size
     DECLARE_ALIGNED_16(float, tmp[WMAPRO_BLOCK_MAX_SIZE]); ///< IMDCT output buffer
     float*           windows[WMAPRO_BLOCK_SIZES];   ///< windows for the different block sizes
 
@@ -762,6 +762,15 @@ static int decode_channel_transform(WMAProDecodeCtx* s)
  */
 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];
@@ -769,7 +778,7 @@ static int decode_coeffs(WMAProDecodeCtx *s, int c)
     int cur_coeff = 0;
     int num_zeros = 0;
     const uint16_t* run;
-    const uint16_t* level;
+    const float* level;
 
     dprintf(s->avctx, "decode coefficients for channel %i\n", c);
 
@@ -797,29 +806,32 @@ static int decode_coeffs(WMAProDecodeCtx *s, int 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;
@@ -981,10 +993,13 @@ static void inverse_channel_transform(WMAProDecodeCtx *s)
                         }
                     }
                 } else if (s->num_channels == 2) {
-                    for (y = sfb[0]; y < FFMIN(sfb[1], s->subframe_len); y++) {
-                        ch_data[0][y] *= 181.0 / 128;
-                        ch_data[1][y] *= 181.0 / 128;
-                    }
+                    int len = FFMIN(sfb[1], s->subframe_len) - sfb[0];
+                    s->dsp.vector_fmul_scalar(ch_data[0] + sfb[0],
+                                              ch_data[0] + sfb[0],
+                                              181.0 / 128, len);
+                    s->dsp.vector_fmul_scalar(ch_data[1] + sfb[0],
+                                              ch_data[1] + sfb[0],
+                                              181.0 / 128, len);
                 }
             }
         }
@@ -1214,10 +1229,10 @@ static int decode_subframe(WMAProDecodeCtx *s)
                             (s->channel[c].max_scale_factor - *sf++) *
                             s->channel[c].scale_factor_step;
                 const float quant = pow(10.0, exp / 20.0);
-                int start;
-
-                for (start = s->cur_sfb_offsets[b]; start < end; start++)
-                    s->tmp[start] = s->channel[c].coeffs[start] * quant;
+                int start = s->cur_sfb_offsets[b];
+                s->dsp.vector_fmul_scalar(s->tmp + start,
+                                          s->channel[c].coeffs + start,
+                                          quant, end - start);
             }
 
             /** apply imdct (ff_imdct_half == DCTIV with reverse) */
@@ -1525,7 +1540,7 @@ static int decode_packet(AVCodecContext *avctx,
     *data_size = (int8_t *)s->samples - (int8_t *)data;
     s->packet_offset = get_bits_count(gb) & 7;
 
-    return get_bits_count(gb) >> 3;
+    return (s->packet_loss) ? AVERROR_INVALIDDATA : get_bits_count(gb) >> 3;
 }
 
 /**
@@ -1557,6 +1572,7 @@ AVCodec wmapro_decoder = {
     NULL,
     decode_end,
     decode_packet,
+    .capabilities = CODEC_CAP_SUBFRAMES,
     .flush= flush,
     .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 9 Professional"),
 };