📄 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 library 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 of the License, or (at your option) any later version. * * This library 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 this library; 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 { QDM2Complex complex[256 + 1] __attribute__((aligned(16))); 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 MPA_INT synth_buf[MPA_MAX_CHANNELS][512*2] __attribute__((aligned(16))); int synth_buf_offset[MPA_MAX_CHANNELS]; int32_t sb_samples[MPA_MAX_CHANNELS][128][SBLIMIT] __attribute__((aligned(16))); /// 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 MPA_INT mpa_window[512] __attribute__((aligned(16)));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 tablestatic 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; value = get_vlc2(gb, vlc->table, vlc->bits, depth); /* stage-2, 3 bits exponent escape sequence */ if (value-- == 0) value = get_bits (gb, get_bits (gb, 3) + 1); /* stage-3, optional */ if (flag) { int tmp = vlc_stage3_values[value]; if ((value & ~3) > 0) tmp += get_bits (gb, (value >> 2)); value = tmp; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -