📄 qdm2.c
字号:
}
} // Loop on B packets
/* calculate maximum indices for FFT coefficients */
for (i = 0, j = -1; i < 5; i++)
if (q->fft_coefs_min_index[i] >= 0) {
if (j >= 0)
q->fft_coefs_max_index[j] = q->fft_coefs_min_index[i];
j = i;
}
if (j >= 0)
q->fft_coefs_max_index[j] = q->fft_coefs_index;
}
static void qdm2_fft_generate_tone (QDM2Context *q, FFTTone *tone)
{
float level, f[6];
int i;
QDM2Complex c;
const double iscale = 2.0*M_PI / 512.0;
tone->phase += tone->phase_shift;
/* calculate current level (maximum amplitude) of tone */
level = fft_tone_envelope_table[tone->duration][tone->time_index] * tone->level;
c.im = level * sin(tone->phase*iscale);
c.re = level * cos(tone->phase*iscale);
/* generate FFT coefficients for tone */
if (tone->duration >= 3 || tone->cutoff >= 3) {
tone->samples_im[0] += c.im;
tone->samples_re[0] += c.re;
tone->samples_im[1] -= c.im;
tone->samples_re[1] -= c.re;
} else {
f[1] = -tone->table[4];
f[0] = tone->table[3] - tone->table[0];
f[2] = 1.0 - tone->table[2] - tone->table[3];
f[3] = tone->table[1] + tone->table[4] - 1.0;
f[4] = tone->table[0] - tone->table[1];
f[5] = tone->table[2];
for (i = 0; i < 2; i++) {
tone->samples_re[fft_cutoff_index_table[tone->cutoff][i]] += c.re * f[i];
tone->samples_im[fft_cutoff_index_table[tone->cutoff][i]] += c.im *((tone->cutoff <= i) ? -f[i] : f[i]);
}
for (i = 0; i < 4; i++) {
tone->samples_re[i] += c.re * f[i+2];
tone->samples_im[i] += c.im * f[i+2];
}
}
/* copy the tone if it has not yet died out */
if (++tone->time_index < ((1 << (5 - tone->duration)) - 1)) {
memcpy(&q->fft_tones[q->fft_tone_end], tone, sizeof(FFTTone));
q->fft_tone_end = (q->fft_tone_end + 1) % 1000;
}
}
static void qdm2_fft_tone_synthesizer (QDM2Context *q, int sub_packet)
{
int i, j, ch;
const double iscale = 0.25 * M_PI;
for (ch = 0; ch < q->channels; ch++) {
memset(q->fft.samples_im[ch], 0, q->fft_size * sizeof(float));
memset(q->fft.samples_re[ch], 0, q->fft_size * sizeof(float));
}
/* apply FFT tones with duration 4 (1 FFT period) */
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;
if (q->fft_coefs[i].sub_packet != sub_packet)
break;
ch = (q->channels == 1) ? 0 : q->fft_coefs[i].channel;
level = (q->fft_coefs[i].exp < 0) ? 0.0 : fft_tone_level_table[q->superblocktype_2_3 ? 0 : 1][q->fft_coefs[i].exp & 63];
c.re = level * cos(q->fft_coefs[i].phase * iscale);
c.im = level * sin(q->fft_coefs[i].phase * iscale);
q->fft.samples_re[ch][q->fft_coefs[i].offset + 0] += c.re;
q->fft.samples_im[ch][q->fft_coefs[i].offset + 0] += c.im;
q->fft.samples_re[ch][q->fft_coefs[i].offset + 1] -= c.re;
q->fft.samples_im[ch][q->fft_coefs[i].offset + 1] -= c.im;
}
/* generate existing FFT tones */
for (i = q->fft_tone_end; i != q->fft_tone_start; ) {
qdm2_fft_generate_tone(q, &q->fft_tones[q->fft_tone_start]);
q->fft_tone_start = (q->fft_tone_start + 1) % 1000;
}
/* create and generate new FFT tones with duration 0 (long) to 3 (short) */
for (i = 0; i < 4; i++)
if (q->fft_coefs_min_index[i] >= 0) {
for (j = q->fft_coefs_min_index[i]; j < q->fft_coefs_max_index[i]; j++) {
int offset, four_i;
FFTTone tone;
if (q->fft_coefs[j].sub_packet != sub_packet)
break;
four_i = (4 - i);
offset = q->fft_coefs[j].offset >> four_i;
ch = (q->channels == 1) ? 0 : q->fft_coefs[j].channel;
if (offset < q->frequency_range) {
if (offset < 2)
tone.cutoff = offset;
else
tone.cutoff = (offset >= 60) ? 3 : 2;
tone.level = (q->fft_coefs[j].exp < 0) ? 0.0 : fft_tone_level_table[q->superblocktype_2_3 ? 0 : 1][q->fft_coefs[j].exp & 63];
tone.samples_im = &q->fft.samples_im[ch][offset];
tone.samples_re = &q->fft.samples_re[ch][offset];
tone.table = (float*)fft_tone_sample_table[i][q->fft_coefs[j].offset - (offset << four_i)];
tone.phase = 64 * q->fft_coefs[j].phase - (offset << 8) - 128;
tone.phase_shift = (2 * q->fft_coefs[j].offset + 1) << (7 - four_i);
tone.duration = i;
tone.time_index = 0;
qdm2_fft_generate_tone(q, &tone);
}
}
q->fft_coefs_min_index[i] = j;
}
}
static void qdm2_calculate_fft (QDM2Context *q, int channel, int sub_packet)
{
const int n = 1 << (q->fft_order - 1);
const int n2 = n >> 1;
const float gain = (q->channels == 1 && q->nb_channels == 2) ? 0.25f : 0.50f;
float c, s, f0, f1, f2, f3;
int i, j;
/* prerotation (or something like that) */
for (i=1; i < n2; i++) {
j = (n - i);
c = q->exptab[i].re;
s = -q->exptab[i].im;
f0 = (q->fft.samples_re[channel][i] - q->fft.samples_re[channel][j]) * gain;
f1 = (q->fft.samples_im[channel][i] + q->fft.samples_im[channel][j]) * gain;
f2 = (q->fft.samples_re[channel][i] + q->fft.samples_re[channel][j]) * gain;
f3 = (q->fft.samples_im[channel][i] - q->fft.samples_im[channel][j]) * gain;
q->fft.complex[i].re = s * f0 - c * f1 + f2;
q->fft.complex[i].im = c * f0 + s * f1 + f3;
q->fft.complex[j].re = -s * f0 + c * f1 + f2;
q->fft.complex[j].im = c * f0 + s * f1 - f3;
}
q->fft.complex[ 0].re = q->fft.samples_re[channel][ 0] * gain * 2.0;
q->fft.complex[ 0].im = q->fft.samples_re[channel][ 0] * gain * 2.0;
q->fft.complex[n2].re = q->fft.samples_re[channel][n2] * gain * 2.0;
q->fft.complex[n2].im = -q->fft.samples_im[channel][n2] * gain * 2.0;
ff_fft_permute(&q->fft_ctx, (FFTComplex *) q->fft.complex);
ff_fft_calc (&q->fft_ctx, (FFTComplex *) q->fft.complex);
/* add samples to output buffer */
for (i = 0; i < ((q->fft_frame_size + 15) & ~15); i++)
q->output_buffer[q->channels * i + channel] += ((float *) q->fft.complex)[i];
}
/**
* @param q context
* @param index subpacket number
*/
static void qdm2_synthesis_filter (QDM2Context *q, int index)
{
OUT_INT samples[MPA_MAX_CHANNELS * MPA_FRAME_SIZE];
int i, k, ch, sb_used, sub_sampling, dither_state = 0;
/* copy sb_samples */
sb_used = QDM2_SB_USED(q->sub_sampling);
for (ch = 0; ch < q->channels; ch++)
for (i = 0; i < 8; i++)
for (k=sb_used; k < SBLIMIT; k++)
q->sb_samples[ch][(8 * index) + i][k] = 0;
for (ch = 0; ch < q->nb_channels; ch++) {
OUT_INT *samples_ptr = samples + ch;
for (i = 0; i < 8; i++) {
ff_mpa_synth_filter(q->synth_buf[ch], &(q->synth_buf_offset[ch]),
mpa_window, &dither_state,
samples_ptr, q->nb_channels,
q->sb_samples[ch][(8 * index) + i]);
samples_ptr += 32 * q->nb_channels;
}
}
/* add samples to output buffer */
sub_sampling = (4 >> q->sub_sampling);
for (ch = 0; ch < q->channels; ch++)
for (i = 0; i < q->frame_size; i++)
q->output_buffer[q->channels * i + ch] += (float)(samples[q->nb_channels * sub_sampling * i + ch] >> (sizeof(OUT_INT)*8-16));
}
/**
* Init static data (does not depend on specific file)
*
* @param q context
*/
static void qdm2_init(QDM2Context *q) {
static int inited = 0;
if (inited != 0)
return;
inited = 1;
qdm2_init_vlc();
ff_mpa_synth_init(mpa_window);
softclip_table_init();
rnd_table_init();
init_noise_samples();
av_log(NULL, AV_LOG_DEBUG, "init done\n");
}
#if 0
static void dump_context(QDM2Context *q)
{
int i;
#define PRINT(a,b) av_log(NULL,AV_LOG_DEBUG," %s = %d\n", a, b);
PRINT("compressed_data",q->compressed_data);
PRINT("compressed_size",q->compressed_size);
PRINT("frame_size",q->frame_size);
PRINT("checksum_size",q->checksum_size);
PRINT("channels",q->channels);
PRINT("nb_channels",q->nb_channels);
PRINT("fft_frame_size",q->fft_frame_size);
PRINT("fft_size",q->fft_size);
PRINT("sub_sampling",q->sub_sampling);
PRINT("fft_order",q->fft_order);
PRINT("group_order",q->group_order);
PRINT("group_size",q->group_size);
PRINT("sub_packet",q->sub_packet);
PRINT("frequency_range",q->frequency_range);
PRINT("has_errors",q->has_errors);
PRINT("fft_tone_end",q->fft_tone_end);
PRINT("fft_tone_start",q->fft_tone_start);
PRINT("fft_coefs_index",q->fft_coefs_index);
PRINT("coeff_per_sb_select",q->coeff_per_sb_select);
PRINT("cm_table_select",q->cm_table_select);
PRINT("noise_idx",q->noise_idx);
for (i = q->fft_tone_start; i < q->fft_tone_end; i++)
{
FFTTone *t = &q->fft_tones[i];
av_log(NULL,AV_LOG_DEBUG,"Tone (%d) dump:\n", i);
av_log(NULL,AV_LOG_DEBUG," level = %f\n", t->level);
// PRINT(" level", t->level);
PRINT(" phase", t->phase);
PRINT(" phase_shift", t->phase_shift);
PRINT(" duration", t->duration);
PRINT(" samples_im", t->samples_im);
PRINT(" samples_re", t->samples_re);
PRINT(" table", t->table);
}
}
#endif
/**
* Init parameters from codec extradata
*/
static int qdm2_decode_init(AVCodecContext *avctx)
{
QDM2Context *s = avctx->priv_data;
uint8_t *extradata;
int extradata_size;
int tmp_val, tmp, size;
int i;
float alpha;
/* extradata parsing
Structure:
wave {
frma (QDM2)
QDCA
QDCP
}
32 size (including this field)
32 tag (=frma)
32 type (=QDM2 or QDMC)
32 size (including this field, in bytes)
32 tag (=QDCA) // maybe mandatory parameters
32 unknown (=1)
32 channels (=2)
32 samplerate (=44100)
32 bitrate (=96000)
32 block size (=4096)
32 frame size (=256) (for one channel)
32 packet size (=1300)
32 size (including this field, in bytes)
32 tag (=QDCP) // maybe some tuneable parameters
32 float1 (=1.0)
32 zero ?
32 float2 (=1.0)
32 float3 (=1.0)
32 unknown (27)
32 unknown (8)
32 zero ?
*/
if (!avctx->extradata || (avctx->extradata_size < 48)) {
av_log(avctx, AV_LOG_ERROR, "extradata missing or truncated\n");
return -1;
}
extradata = avctx->extradata;
extradata_size = avctx->extradata_size;
while (extradata_size > 7) {
if (!memcmp(extradata, "frmaQDM", 7))
break;
extradata++;
extradata_size--;
}
if (extradata_size < 12) {
av_log(avctx, AV_LOG_ERROR, "not enough extradata (%i)\n",
extradata_size);
return -1;
}
if (memcmp(extradata, "frmaQDM", 7)) {
av_log(avctx, AV_LOG_ERROR, "invalid headers, QDM? not found\n");
return -1;
}
if (extradata[7] == 'C') {
// s->is_qdmc = 1;
av_log(avctx, AV_LOG_ERROR, "stream is QDMC version 1, which is not supported\n");
return -1;
}
extradata += 8;
extradata_size -= 8;
size = AV_RB32(extradata);
if(size > extradata_size){
av_log(avctx, AV_LOG_ERROR, "extradata size too small, %i < %i\n",
extradata_size, size);
return -1;
}
extradata += 4;
av_log(avctx, AV_LOG_DEBUG, "size: %d\n", size);
if (AV_RB32(extradata) != MKBETAG('Q','D','C','A')) {
av_log(avctx, AV_LOG_ERROR, "invalid extradata
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -