|
|
|
@ -37,6 +37,7 @@ |
|
|
|
|
#include "libavutil/channel_layout.h" |
|
|
|
|
#include "libavutil/mem_internal.h" |
|
|
|
|
#include "libavutil/thread.h" |
|
|
|
|
#include "libavutil/tx.h" |
|
|
|
|
|
|
|
|
|
#define BITSTREAM_READER_LE |
|
|
|
|
#include "avcodec.h" |
|
|
|
@ -46,7 +47,6 @@ |
|
|
|
|
#include "decode.h" |
|
|
|
|
#include "mpegaudio.h" |
|
|
|
|
#include "mpegaudiodsp.h" |
|
|
|
|
#include "rdft.h" |
|
|
|
|
|
|
|
|
|
#include "qdm2_tablegen.h" |
|
|
|
|
|
|
|
|
@ -96,14 +96,9 @@ typedef struct QDM2SubPNode { |
|
|
|
|
struct QDM2SubPNode *next; ///< pointer to next packet in the list, NULL if leaf node
|
|
|
|
|
} QDM2SubPNode; |
|
|
|
|
|
|
|
|
|
typedef struct QDM2Complex { |
|
|
|
|
float re; |
|
|
|
|
float im; |
|
|
|
|
} QDM2Complex; |
|
|
|
|
|
|
|
|
|
typedef struct FFTTone { |
|
|
|
|
float level; |
|
|
|
|
QDM2Complex *complex; |
|
|
|
|
AVComplexFloat *complex; |
|
|
|
|
const float *table; |
|
|
|
|
int phase; |
|
|
|
|
int phase_shift; |
|
|
|
@ -121,7 +116,8 @@ typedef struct FFTCoefficient { |
|
|
|
|
} FFTCoefficient; |
|
|
|
|
|
|
|
|
|
typedef struct QDM2FFT { |
|
|
|
|
DECLARE_ALIGNED(32, QDM2Complex, complex)[MPA_MAX_CHANNELS][256]; |
|
|
|
|
DECLARE_ALIGNED(32, AVComplexFloat, complex)[MPA_MAX_CHANNELS][256 + 1]; |
|
|
|
|
DECLARE_ALIGNED(32, AVComplexFloat, temp)[MPA_MAX_CHANNELS][256]; |
|
|
|
|
} QDM2FFT; |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@ -161,7 +157,8 @@ typedef struct QDM2Context { |
|
|
|
|
int fft_coefs_min_index[5]; |
|
|
|
|
int fft_coefs_max_index[5]; |
|
|
|
|
int fft_level_exp[6]; |
|
|
|
|
RDFTContext rdft_ctx; |
|
|
|
|
AVTXContext *rdft_ctx; |
|
|
|
|
av_tx_fn rdft_fn; |
|
|
|
|
QDM2FFT fft; |
|
|
|
|
|
|
|
|
|
/// I/O data
|
|
|
|
@ -1428,7 +1425,7 @@ static void qdm2_fft_generate_tone(QDM2Context *q, FFTTone *tone) |
|
|
|
|
{ |
|
|
|
|
float level, f[6]; |
|
|
|
|
int i; |
|
|
|
|
QDM2Complex c; |
|
|
|
|
AVComplexFloat c; |
|
|
|
|
const double iscale = 2.0 * M_PI / 512.0; |
|
|
|
|
|
|
|
|
|
tone->phase += tone->phase_shift; |
|
|
|
@ -1476,7 +1473,7 @@ static void qdm2_fft_tone_synthesizer(QDM2Context *q, int sub_packet) |
|
|
|
|
const double iscale = 0.25 * M_PI; |
|
|
|
|
|
|
|
|
|
for (ch = 0; ch < q->channels; ch++) { |
|
|
|
|
memset(q->fft.complex[ch], 0, q->fft_size * sizeof(QDM2Complex)); |
|
|
|
|
memset(q->fft.complex[ch], 0, q->fft_size * sizeof(AVComplexFloat)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -1484,7 +1481,7 @@ static void qdm2_fft_tone_synthesizer(QDM2Context *q, int sub_packet) |
|
|
|
|
if (q->fft_coefs_min_index[4] >= 0) |
|
|
|
|
for (i = q->fft_coefs_min_index[4]; i < q->fft_coefs_max_index[4]; i++) { |
|
|
|
|
float level; |
|
|
|
|
QDM2Complex c; |
|
|
|
|
AVComplexFloat c; |
|
|
|
|
|
|
|
|
|
if (q->fft_coefs[i].sub_packet != sub_packet) |
|
|
|
|
break; |
|
|
|
@ -1545,14 +1542,19 @@ static void qdm2_calculate_fft(QDM2Context *q, int channel, int sub_packet) |
|
|
|
|
{ |
|
|
|
|
const float gain = (q->channels == 1 && q->nb_channels == 2) ? 0.5f : 1.0f; |
|
|
|
|
float *out = q->output_buffer + channel; |
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
q->fft.complex[channel][0].re *= 2.0f; |
|
|
|
|
q->fft.complex[channel][0].im = 0.0f; |
|
|
|
|
q->rdft_ctx.rdft_calc(&q->rdft_ctx, (FFTSample *)q->fft.complex[channel]); |
|
|
|
|
q->fft.complex[channel][q->fft_size].re = 0.0f; |
|
|
|
|
q->fft.complex[channel][q->fft_size].im = 0.0f; |
|
|
|
|
|
|
|
|
|
q->rdft_fn(q->rdft_ctx, q->fft.temp[channel], q->fft.complex[channel], |
|
|
|
|
sizeof(AVComplexFloat)); |
|
|
|
|
|
|
|
|
|
/* add samples to output buffer */ |
|
|
|
|
for (i = 0; i < FFALIGN(q->fft_size, 8); i++) { |
|
|
|
|
out[0] += q->fft.complex[channel][i].re * gain; |
|
|
|
|
out[q->channels] += q->fft.complex[channel][i].im * gain; |
|
|
|
|
for (int i = 0; i < FFALIGN(q->fft_size, 8); i++) { |
|
|
|
|
out[0] += q->fft.temp[channel][i].re * gain; |
|
|
|
|
out[q->channels] += q->fft.temp[channel][i].im * gain; |
|
|
|
|
out += 2 * q->channels; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -1613,7 +1615,8 @@ static av_cold int qdm2_decode_init(AVCodecContext *avctx) |
|
|
|
|
{ |
|
|
|
|
static AVOnce init_static_once = AV_ONCE_INIT; |
|
|
|
|
QDM2Context *s = avctx->priv_data; |
|
|
|
|
int tmp_val, tmp, size; |
|
|
|
|
int ret, tmp_val, tmp, size; |
|
|
|
|
float scale = 1.0f / 2.0f; |
|
|
|
|
GetByteContext gb; |
|
|
|
|
|
|
|
|
|
/* extradata parsing
|
|
|
|
@ -1756,7 +1759,10 @@ static av_cold int qdm2_decode_init(AVCodecContext *avctx) |
|
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ff_rdft_init(&s->rdft_ctx, s->fft_order, IDFT_C2R); |
|
|
|
|
ret = av_tx_init(&s->rdft_ctx, &s->rdft_fn, AV_TX_FLOAT_RDFT, 1, 2*s->fft_size, &scale, 0); |
|
|
|
|
if (ret < 0) |
|
|
|
|
return ret; |
|
|
|
|
|
|
|
|
|
ff_mpadsp_init(&s->mpadsp); |
|
|
|
|
|
|
|
|
|
avctx->sample_fmt = AV_SAMPLE_FMT_S16; |
|
|
|
@ -1770,7 +1776,7 @@ static av_cold int qdm2_decode_close(AVCodecContext *avctx) |
|
|
|
|
{ |
|
|
|
|
QDM2Context *s = avctx->priv_data; |
|
|
|
|
|
|
|
|
|
ff_rdft_end(&s->rdft_ctx); |
|
|
|
|
av_tx_uninit(&s->rdft_ctx); |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|