⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qdm2.c

📁 ffmpeg的完整源代码和作者自己写的文档。不但有在Linux的工程哦
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
 * 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 + -