* For licencing details see COPYING.LIB.
*/
-/** * \file wmadec_filter.c paraslash's WMA decoder. */
+/** \file wmadec_filter.c paraslash's WMA decoder. */
/*
* This decoder handles Microsoft Windows Media Audio data version 2.
#include <sys/time.h>
#include <inttypes.h>
-#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "sched.h"
#include "filter.h"
#include "bitstream.h"
-#include "mdct.h"
+#include "imdct.h"
#include "wma.h"
#include "wmadata.h"
int next_block_len_bits; ///< log2 of next block length
int prev_block_len_bits; ///< log2 of prev block length
int block_len; ///< block length in samples
- int block_num; ///< block number in current frame
int block_pos; ///< current position in frame
uint8_t ms_stereo; ///< true if mid/side stereo mode
uint8_t channel_coded[MAX_CHANNELS]; ///< true if channel is coded
};
#define EXPVLCBITS 8
-#define EXPMAX ((19+EXPVLCBITS-1)/EXPVLCBITS)
+#define EXPMAX ((19 + EXPVLCBITS - 1) / EXPVLCBITS)
#define HGAINVLCBITS 9
-#define HGAINMAX ((13+HGAINVLCBITS-1)/HGAINVLCBITS)
+#define HGAINMAX ((13 + HGAINVLCBITS - 1) / HGAINVLCBITS)
#define VLCBITS 9
-#define VLCMAX ((22+VLCBITS-1)/VLCBITS)
+#define VLCMAX ((22 + VLCBITS - 1) / VLCBITS)
+
+DECLARE_ALIGNED(16, float, ff_sine_128[128]);
+DECLARE_ALIGNED(16, float, ff_sine_256[256]);
+DECLARE_ALIGNED(16, float, ff_sine_512[512]);
+DECLARE_ALIGNED(16, float, ff_sine_1024[1024]);
+DECLARE_ALIGNED(16, float, ff_sine_2048[2048]);
+DECLARE_ALIGNED(16, float, ff_sine_4096[4096]);
+
+static float *ff_sine_windows[6] = {
+ ff_sine_128, ff_sine_256, ff_sine_512, ff_sine_1024,
+ ff_sine_2048, ff_sine_4096
+};
-static int wmadec_cleanup(struct private_wmadec_data *s)
+/* Generate a sine window. */
+static void sine_window_init(float *window, int n)
{
int i;
- for (i = 0; i < s->nb_block_sizes; i++)
- mdct_end(s->mdct_ctx[i]);
+ for (i = 0; i < n; i++)
+ window[i] = sinf((i + 0.5) * (M_PI / (2.0 * n)));
+}
+static void wmadec_cleanup(struct private_wmadec_data *s)
+{
+ int i;
+
+ for (i = 0; i < s->nb_block_sizes; i++)
+ imdct_end(s->mdct_ctx[i]);
if (s->use_exp_vlc)
free_vlc(&s->exp_vlc);
if (s->use_noise_coding)
free(s->level_table[i]);
free(s->int_table[i]);
}
- return 0;
}
/* XXX: use same run/length optimization as mpeg decoders */
init_vlc(vlc, VLCBITS, n, table_bits, 1, 1, table_codes, 4, 4);
- run_table = para_malloc(n * sizeof (uint16_t));
- level_table = para_malloc(n * sizeof (uint16_t));
- int_table = para_malloc(n * sizeof (uint16_t));
+ run_table = para_malloc(n * sizeof(uint16_t));
+ level_table = para_malloc(n * sizeof(uint16_t));
+ int_table = para_malloc(n * sizeof(uint16_t));
i = 2;
level = 1;
k = 0;
if (nb > nb_max)
nb = nb_max;
s->nb_block_sizes = nb + 1;
- } else {
+ } else
s->nb_block_sizes = 1;
- }
/* init rate dependent parameters */
s->use_noise_coding = 1;
struct private_wmadec_data *s;
int ret, i;
- if (len < 18)
- return 0;
-
PARA_NOTICE_LOG("initial buf: %d bytes\n", len);
s = para_calloc(sizeof(*s));
ret = read_asf_header(initial_buf, len, &s->ahi);
- if (ret < 0)
+ if (ret <= 0) {
+ free(s);
return ret;
+ }
s->use_exp_vlc = s->ahi.flags2 & 0x0001;
s->use_bit_reservoir = s->ahi.flags2 & 0x0002;
return ret;
/* init MDCT */
for (i = 0; i < s->nb_block_sizes; i++) {
- ret = mdct_init(s->frame_len_bits - i + 1, 1, &s->mdct_ctx[i]);
+ ret = imdct_init(s->frame_len_bits - i + 1, &s->mdct_ctx[i]);
if (ret < 0)
return ret;
}
if (s->use_noise_coding) {
PARA_INFO_LOG("using noise coding\n");
init_vlc(&s->hgain_vlc, HGAINVLCBITS,
- sizeof (ff_wma_hgain_huffbits), ff_wma_hgain_huffbits,
+ sizeof(ff_wma_hgain_huffbits), ff_wma_hgain_huffbits,
1, 1, ff_wma_hgain_huffcodes, 2, 2);
}
if (s->use_exp_vlc) {
PARA_INFO_LOG("using exp_vlc\n");
init_vlc(&s->exp_vlc, EXPVLCBITS,
- sizeof (ff_wma_scale_huffbits), ff_wma_scale_huffbits,
+ sizeof(ff_wma_scale_huffbits), ff_wma_scale_huffbits,
1, 1, ff_wma_scale_huffcodes, 4, 4);
} else {
PARA_INFO_LOG("using curve\n");
return 0;
}
-static void vector_fmul_add(float *dst, const float *src0, const float *src1,
- const float *src2, int src3, int len, int step)
+/* 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 * step] = src0[i] * src1[i] + src2[i] + src3;
+ dst[i] = src0[i] * src1[i] + src2[i];
}
-static void vector_fmul_reverse_c(float *dst, const float *src0,
+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];
if (s->block_len_bits <= s->prev_block_len_bits) {
block_len = s->block_len;
bsize = s->frame_len_bits - s->block_len_bits;
-
- vector_fmul_add(out, in, s->windows[bsize],
- out, 0, block_len, 1);
-
+ vector_mult_add(out, in, s->windows[bsize], out, block_len);
} else {
block_len = 1 << s->prev_block_len_bits;
n = (s->block_len - block_len) / 2;
bsize = s->frame_len_bits - s->prev_block_len_bits;
-
- vector_fmul_add(out + n, in + n, s->windows[bsize],
- out + n, 0, block_len, 1);
-
+ vector_mult_add(out + n, in + n, s->windows[bsize], out + n,
+ block_len);
memcpy(out + n + block_len, in + n + block_len,
- n * sizeof (float));
+ n * sizeof(float));
}
-
out += s->block_len;
in += s->block_len;
-
/* right part */
if (s->block_len_bits <= s->next_block_len_bits) {
block_len = s->block_len;
bsize = s->frame_len_bits - s->block_len_bits;
-
- vector_fmul_reverse_c(out, in, s->windows[bsize], block_len);
-
+ vector_mult_reverse(out, in, s->windows[bsize], block_len);
} else {
block_len = 1 << s->next_block_len_bits;
n = (s->block_len - block_len) / 2;
bsize = s->frame_len_bits - s->next_block_len_bits;
-
- memcpy(out, in, n * sizeof (float));
-
- vector_fmul_reverse_c(out + n, in + n, s->windows[bsize],
- block_len);
-
- memset(out + n + block_len, 0, n * sizeof (float));
+ memcpy(out, in, n * sizeof(float));
+ vector_mult_reverse(out + n, in + n, s->windows[bsize],
+ block_len);
+ memset(out + n + block_len, 0, n * sizeof(float));
}
}
if ((s->block_pos + s->block_len) > s->frame_len)
return -E_INCOHERENT_BLOCK_LEN;
- if (s->ahi.channels == 2) {
+ if (s->ahi.channels == 2)
s->ms_stereo = get_bits1(&s->gb);
- }
v = 0;
for (ch = 0; ch < s->ahi.channels; ch++) {
int a = get_bits1(&s->gb);
/* complex coding */
if (s->use_noise_coding) {
-
for (ch = 0; ch < s->ahi.channels; ch++) {
if (s->channel_coded[ch]) {
int i, m, a;
if (s->channel_coded[ch])
imdct(s->mdct_ctx[bsize], s->output, s->coefs[ch]);
else if (!(s->ms_stereo && ch == 1))
- memset(s->output, 0, sizeof (s->output));
+ memset(s->output, 0, sizeof(s->output));
/* multiply by the window and add in the frame */
index = (s->frame_len / 2) + s->block_pos - n4;
}
/* update block number */
- s->block_num++;
s->block_pos += s->block_len;
if (s->block_pos >= s->frame_len)
return 1;
}
/* Decode a frame of frame_len samples. */
-static int wma_decode_frame(struct private_wmadec_data *s, int16_t * samples)
+static int wma_decode_frame(struct private_wmadec_data *s, int16_t *samples)
{
int ret, i, n, ch, incr;
int16_t *ptr;
float *iptr;
/* read each block */
- s->block_num = 0;
s->block_pos = 0;
for (;;) {
ret = wma_decode_block(s);
}
/* prepare for next block */
memmove(&s->frame_out[ch][0], &s->frame_out[ch][s->frame_len],
- s->frame_len * sizeof (float));
+ s->frame_len * sizeof(float));
}
return 0;
}
*q++ = get_bits(&s->gb, 8);
len -= 8;
}
- if (len > 0) {
+ if (len > 0)
*q++ = get_bits(&s->gb, len) << (8 - len);
- }
/* XXX: bit_offset bits into last frame */
init_get_bits(&s->gb, s->last_superframe,
pos >>= 3;
len = buf_size - pos;
ret = -E_WMA_BAD_SUPERFRAME;
- if (len > MAX_CODED_SUPERFRAME_SIZE || len < 0) {
+ if (len > MAX_CODED_SUPERFRAME_SIZE || len < 0)
goto fail;
- }
s->last_superframe_len = len;
memcpy(s->last_superframe, buf + pos, len);
} else {
static void wmadec_close(struct filter_node *fn)
{
struct private_wmadec_data *pwd = fn->private_data;
+
if (!pwd)
return;
wmadec_cleanup(pwd);