📄 qdm2.c
字号:
/*
* QDM2 compatible decoder
* Copyright (c) 2003 Ewald Snel
* Copyright (c) 2005 Benjamin Larsson
* Copyright (c) 2005 Alex Beregszaszi
* Copyright (c) 2005 Roberto Togni
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file qdm2.c
* QDM2 decoder
* @author Ewald Snel, Benjamin Larsson, Alex Beregszaszi, Roberto Togni
* The decoder is not perfect yet, there are still some distortions
* especially on files encoded with 16 or 8 subbands.
*/
#include <math.h>
#include <stddef.h>
#include <stdio.h>
#define ALT_BITSTREAM_READER_LE
#include "avcodec.h"
#include "bitstream.h"
#include "dsputil.h"
#ifdef CONFIG_MPEGAUDIO_HP
#define USE_HIGHPRECISION
#endif
#include "mpegaudio.h"
#include "qdm2data.h"
#undef NDEBUG
#include <assert.h>
#define SOFTCLIP_THRESHOLD 27600
#define HARDCLIP_THRESHOLD 35716
#define QDM2_LIST_ADD(list, size, packet) \
do { \
if (size > 0) { \
list[size - 1].next = &list[size]; \
} \
list[size].packet = packet; \
list[size].next = NULL; \
size++; \
} while(0)
// Result is 8, 16 or 30
#define QDM2_SB_USED(sub_sampling) (((sub_sampling) >= 2) ? 30 : 8 << (sub_sampling))
#define FIX_NOISE_IDX(noise_idx) \
if ((noise_idx) >= 3840) \
(noise_idx) -= 3840; \
#define SB_DITHERING_NOISE(sb,noise_idx) (noise_table[(noise_idx)++] * sb_noise_attenuation[(sb)])
#define BITS_LEFT(length,gb) ((length) - get_bits_count ((gb)))
#define SAMPLES_NEEDED \
av_log (NULL,AV_LOG_INFO,"This file triggers some untested code. Please contact the developers.\n");
#define SAMPLES_NEEDED_2(why) \
av_log (NULL,AV_LOG_INFO,"This file triggers some missing code. Please contact the developers.\nPosition: %s\n",why);
typedef int8_t sb_int8_array[2][30][64];
/**
* Subpacket
*/
typedef struct {
int type; ///< subpacket type
unsigned int size; ///< subpacket size
const uint8_t *data; ///< pointer to subpacket data (points to input data buffer, it's not a private copy)
} QDM2SubPacket;
/**
* A node in the subpacket list
*/
typedef struct _QDM2SubPNode {
QDM2SubPacket *packet; ///< packet
struct _QDM2SubPNode *next; ///< pointer to next packet in the list, NULL if leaf node
} QDM2SubPNode;
typedef struct {
float level;
float *samples_im;
float *samples_re;
float *table;
int phase;
int phase_shift;
int duration;
short time_index;
short cutoff;
} FFTTone;
typedef struct {
int16_t sub_packet;
uint8_t channel;
int16_t offset;
int16_t exp;
uint8_t phase;
} FFTCoefficient;
typedef struct {
float re;
float im;
} QDM2Complex;
typedef struct {
DECLARE_ALIGNED_16(QDM2Complex, complex[256 + 1]);
float samples_im[MPA_MAX_CHANNELS][256];
float samples_re[MPA_MAX_CHANNELS][256];
} QDM2FFT;
/**
* QDM2 decoder context
*/
typedef struct {
/// Parameters from codec header, do not change during playback
int nb_channels; ///< number of channels
int channels; ///< number of channels
int group_size; ///< size of frame group (16 frames per group)
int fft_size; ///< size of FFT, in complex numbers
int checksum_size; ///< size of data block, used also for checksum
/// Parameters built from header parameters, do not change during playback
int group_order; ///< order of frame group
int fft_order; ///< order of FFT (actually fftorder+1)
int fft_frame_size; ///< size of fft frame, in components (1 comples = re + im)
int frame_size; ///< size of data frame
int frequency_range;
int sub_sampling; ///< subsampling: 0=25%, 1=50%, 2=100% */
int coeff_per_sb_select; ///< selector for "num. of coeffs. per subband" tables. Can be 0, 1, 2
int cm_table_select; ///< selector for "coding method" tables. Can be 0, 1 (from init: 0-4)
/// Packets and packet lists
QDM2SubPacket sub_packets[16]; ///< the packets themselves
QDM2SubPNode sub_packet_list_A[16]; ///< list of all packets
QDM2SubPNode sub_packet_list_B[16]; ///< FFT packets B are on list
int sub_packets_B; ///< number of packets on 'B' list
QDM2SubPNode sub_packet_list_C[16]; ///< packets with errors?
QDM2SubPNode sub_packet_list_D[16]; ///< DCT packets
/// FFT and tones
FFTTone fft_tones[1000];
int fft_tone_start;
int fft_tone_end;
FFTCoefficient fft_coefs[1000];
int fft_coefs_index;
int fft_coefs_min_index[5];
int fft_coefs_max_index[5];
int fft_level_exp[6];
FFTContext fft_ctx;
FFTComplex exptab[128];
QDM2FFT fft;
/// I/O data
uint8_t *compressed_data;
int compressed_size;
float output_buffer[1024];
/// Synthesis filter
DECLARE_ALIGNED_16(MPA_INT, synth_buf[MPA_MAX_CHANNELS][512*2]);
int synth_buf_offset[MPA_MAX_CHANNELS];
DECLARE_ALIGNED_16(int32_t, sb_samples[MPA_MAX_CHANNELS][128][SBLIMIT]);
/// Mixed temporary data used in decoding
float tone_level[MPA_MAX_CHANNELS][30][64];
int8_t coding_method[MPA_MAX_CHANNELS][30][64];
int8_t quantized_coeffs[MPA_MAX_CHANNELS][10][8];
int8_t tone_level_idx_base[MPA_MAX_CHANNELS][30][8];
int8_t tone_level_idx_hi1[MPA_MAX_CHANNELS][3][8][8];
int8_t tone_level_idx_mid[MPA_MAX_CHANNELS][26][8];
int8_t tone_level_idx_hi2[MPA_MAX_CHANNELS][26];
int8_t tone_level_idx[MPA_MAX_CHANNELS][30][64];
int8_t tone_level_idx_temp[MPA_MAX_CHANNELS][30][64];
// Flags
int has_errors; ///< packet has errors
int superblocktype_2_3; ///< select fft tables and some algorithm based on superblock type
int do_synth_filter; ///< used to perform or skip synthesis filter
int sub_packet;
int noise_idx; ///< index for dithering noise table
} QDM2Context;
static uint8_t empty_buffer[FF_INPUT_BUFFER_PADDING_SIZE];
static VLC vlc_tab_level;
static VLC vlc_tab_diff;
static VLC vlc_tab_run;
static VLC fft_level_exp_alt_vlc;
static VLC fft_level_exp_vlc;
static VLC fft_stereo_exp_vlc;
static VLC fft_stereo_phase_vlc;
static VLC vlc_tab_tone_level_idx_hi1;
static VLC vlc_tab_tone_level_idx_mid;
static VLC vlc_tab_tone_level_idx_hi2;
static VLC vlc_tab_type30;
static VLC vlc_tab_type34;
static VLC vlc_tab_fft_tone_offset[5];
static uint16_t softclip_table[HARDCLIP_THRESHOLD - SOFTCLIP_THRESHOLD + 1];
static float noise_table[4096];
static uint8_t random_dequant_index[256][5];
static uint8_t random_dequant_type24[128][3];
static float noise_samples[128];
static DECLARE_ALIGNED_16(MPA_INT, mpa_window[512]);
static void softclip_table_init(void) {
int i;
double dfl = SOFTCLIP_THRESHOLD - 32767;
float delta = 1.0 / -dfl;
for (i = 0; i < HARDCLIP_THRESHOLD - SOFTCLIP_THRESHOLD + 1; i++)
softclip_table[i] = SOFTCLIP_THRESHOLD - ((int)(sin((float)i * delta) * dfl) & 0x0000FFFF);
}
// random generated table
static void rnd_table_init(void) {
int i,j;
uint32_t ldw,hdw;
uint64_t tmp64_1;
uint64_t random_seed = 0;
float delta = 1.0 / 16384.0;
for(i = 0; i < 4096 ;i++) {
random_seed = random_seed * 214013 + 2531011;
noise_table[i] = (delta * (float)(((int32_t)random_seed >> 16) & 0x00007FFF)- 1.0) * 1.3;
}
for (i = 0; i < 256 ;i++) {
random_seed = 81;
ldw = i;
for (j = 0; j < 5 ;j++) {
random_dequant_index[i][j] = (uint8_t)((ldw / random_seed) & 0xFF);
ldw = (uint32_t)ldw % (uint32_t)random_seed;
tmp64_1 = (random_seed * 0x55555556);
hdw = (uint32_t)(tmp64_1 >> 32);
random_seed = (uint64_t)(hdw + (ldw >> 31));
}
}
for (i = 0; i < 128 ;i++) {
random_seed = 25;
ldw = i;
for (j = 0; j < 3 ;j++) {
random_dequant_type24[i][j] = (uint8_t)((ldw / random_seed) & 0xFF);
ldw = (uint32_t)ldw % (uint32_t)random_seed;
tmp64_1 = (random_seed * 0x66666667);
hdw = (uint32_t)(tmp64_1 >> 33);
random_seed = hdw + (ldw >> 31);
}
}
}
static void init_noise_samples(void) {
int i;
int random_seed = 0;
float delta = 1.0 / 16384.0;
for (i = 0; i < 128;i++) {
random_seed = random_seed * 214013 + 2531011;
noise_samples[i] = (delta * (float)((random_seed >> 16) & 0x00007fff) - 1.0);
}
}
static void qdm2_init_vlc(void)
{
init_vlc (&vlc_tab_level, 8, 24,
vlc_tab_level_huffbits, 1, 1,
vlc_tab_level_huffcodes, 2, 2, INIT_VLC_USE_STATIC | INIT_VLC_LE);
init_vlc (&vlc_tab_diff, 8, 37,
vlc_tab_diff_huffbits, 1, 1,
vlc_tab_diff_huffcodes, 2, 2, INIT_VLC_USE_STATIC | INIT_VLC_LE);
init_vlc (&vlc_tab_run, 5, 6,
vlc_tab_run_huffbits, 1, 1,
vlc_tab_run_huffcodes, 1, 1, INIT_VLC_USE_STATIC | INIT_VLC_LE);
init_vlc (&fft_level_exp_alt_vlc, 8, 28,
fft_level_exp_alt_huffbits, 1, 1,
fft_level_exp_alt_huffcodes, 2, 2, INIT_VLC_USE_STATIC | INIT_VLC_LE);
init_vlc (&fft_level_exp_vlc, 8, 20,
fft_level_exp_huffbits, 1, 1,
fft_level_exp_huffcodes, 2, 2, INIT_VLC_USE_STATIC | INIT_VLC_LE);
init_vlc (&fft_stereo_exp_vlc, 6, 7,
fft_stereo_exp_huffbits, 1, 1,
fft_stereo_exp_huffcodes, 1, 1, INIT_VLC_USE_STATIC | INIT_VLC_LE);
init_vlc (&fft_stereo_phase_vlc, 6, 9,
fft_stereo_phase_huffbits, 1, 1,
fft_stereo_phase_huffcodes, 1, 1, INIT_VLC_USE_STATIC | INIT_VLC_LE);
init_vlc (&vlc_tab_tone_level_idx_hi1, 8, 20,
vlc_tab_tone_level_idx_hi1_huffbits, 1, 1,
vlc_tab_tone_level_idx_hi1_huffcodes, 2, 2, INIT_VLC_USE_STATIC | INIT_VLC_LE);
init_vlc (&vlc_tab_tone_level_idx_mid, 8, 24,
vlc_tab_tone_level_idx_mid_huffbits, 1, 1,
vlc_tab_tone_level_idx_mid_huffcodes, 2, 2, INIT_VLC_USE_STATIC | INIT_VLC_LE);
init_vlc (&vlc_tab_tone_level_idx_hi2, 8, 24,
vlc_tab_tone_level_idx_hi2_huffbits, 1, 1,
vlc_tab_tone_level_idx_hi2_huffcodes, 2, 2, INIT_VLC_USE_STATIC | INIT_VLC_LE);
init_vlc (&vlc_tab_type30, 6, 9,
vlc_tab_type30_huffbits, 1, 1,
vlc_tab_type30_huffcodes, 1, 1, INIT_VLC_USE_STATIC | INIT_VLC_LE);
init_vlc (&vlc_tab_type34, 5, 10,
vlc_tab_type34_huffbits, 1, 1,
vlc_tab_type34_huffcodes, 1, 1, INIT_VLC_USE_STATIC | INIT_VLC_LE);
init_vlc (&vlc_tab_fft_tone_offset[0], 8, 23,
vlc_tab_fft_tone_offset_0_huffbits, 1, 1,
vlc_tab_fft_tone_offset_0_huffcodes, 2, 2, INIT_VLC_USE_STATIC | INIT_VLC_LE);
init_vlc (&vlc_tab_fft_tone_offset[1], 8, 28,
vlc_tab_fft_tone_offset_1_huffbits, 1, 1,
vlc_tab_fft_tone_offset_1_huffcodes, 2, 2, INIT_VLC_USE_STATIC | INIT_VLC_LE);
init_vlc (&vlc_tab_fft_tone_offset[2], 8, 32,
vlc_tab_fft_tone_offset_2_huffbits, 1, 1,
vlc_tab_fft_tone_offset_2_huffcodes, 2, 2, INIT_VLC_USE_STATIC | INIT_VLC_LE);
init_vlc (&vlc_tab_fft_tone_offset[3], 8, 35,
vlc_tab_fft_tone_offset_3_huffbits, 1, 1,
vlc_tab_fft_tone_offset_3_huffcodes, 2, 2, INIT_VLC_USE_STATIC | INIT_VLC_LE);
init_vlc (&vlc_tab_fft_tone_offset[4], 8, 38,
vlc_tab_fft_tone_offset_4_huffbits, 1, 1,
vlc_tab_fft_tone_offset_4_huffcodes, 2, 2, INIT_VLC_USE_STATIC | INIT_VLC_LE);
}
/* for floating point to fixed point conversion */
static float f2i_scale = (float) (1 << (FRAC_BITS - 15));
static int qdm2_get_vlc (GetBitContext *gb, VLC *vlc, int flag, int depth)
{
int value;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -