[FFmpeg-devel] [RFC][WIP][PATCH 1/3] avcodec: add AC-4 decoder
Paul B Mahol
onemda at gmail.com
Thu Mar 5 00:26:31 EET 2020
This work is sponsored by VideoLAN.
Signed-off-by: Paul B Mahol <onemda at gmail.com>
---
libavcodec/Makefile | 1 +
libavcodec/ac4dec.c | 5393 ++++++++++++++++++++++++++++++++++++++
libavcodec/ac4dec_data.h | 1484 +++++++++++
libavcodec/allcodecs.c | 1 +
libavcodec/avcodec.h | 1 +
libavcodec/codec_desc.c | 7 +
libavcodec/kbdwin.h | 2 +-
libavformat/isom.c | 1 +
8 files changed, 6889 insertions(+), 1 deletion(-)
create mode 100644 libavcodec/ac4dec.c
create mode 100644 libavcodec/ac4dec_data.h
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index f1c032b456..8bc11b4e77 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -173,6 +173,7 @@ OBJS-$(CONFIG_AC3_FIXED_DECODER) += ac3dec_fixed.o ac3dec_data.o ac3.o kbd
OBJS-$(CONFIG_AC3_ENCODER) += ac3enc_float.o ac3enc.o ac3tab.o \
ac3.o kbdwin.o
OBJS-$(CONFIG_AC3_FIXED_ENCODER) += ac3enc_fixed.o ac3enc.o ac3tab.o ac3.o
+OBJS-$(CONFIG_AC4_DECODER) += ac4dec.o
OBJS-$(CONFIG_ACELP_KELVIN_DECODER) += g729dec.o lsp.o celp_math.o celp_filters.o acelp_filters.o acelp_pitch_delay.o acelp_vectors.o g729postfilter.o
OBJS-$(CONFIG_AGM_DECODER) += agm.o
OBJS-$(CONFIG_AIC_DECODER) += aic.o
diff --git a/libavcodec/ac4dec.c b/libavcodec/ac4dec.c
new file mode 100644
index 0000000000..408466c9eb
--- /dev/null
+++ b/libavcodec/ac4dec.c
@@ -0,0 +1,5393 @@
+/*
+ * AC-4 Audio Decoder
+ *
+ * Copyright (c) 2019 Paul B Mahol
+ *
+ * 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
+ */
+
+#define ASSERT_LEVEL 5
+#include "libavutil/avassert.h"
+#include "libavutil/tx.h"
+#include "libavutil/channel_layout.h"
+#include "libavutil/float_dsp.h"
+#include "libavutil/thread.h"
+#include "libavutil/qsort.h"
+
+#include "ac4dec_data.h"
+#include "avcodec.h"
+#include "get_bits.h"
+#include "internal.h"
+#include "kbdwin.h"
+#include "unary.h"
+
+typedef struct EMDFInfo {
+ int version;
+ int key_id;
+ int substream_index;
+} EMDFInfo;
+
+typedef struct SubstreamChannelParameters {
+ uint8_t long_frame;
+ uint8_t transf_length_idx[2];
+ int transf_length[2];
+
+ uint8_t different_framing;
+ uint8_t max_sfb_side[2];
+ uint8_t max_sfb[2];
+ uint8_t scale_factor_grouping[15];
+
+ uint8_t num_windows;
+ uint8_t num_window_groups;
+ uint8_t window_to_group[16];
+ uint8_t num_win_in_group[16];
+
+ uint8_t dual_maxsfb;
+ uint8_t side_limited;
+ uint8_t side_channel;
+} SubstreamChannelParameters;
+
+typedef struct SubstreamChannel {
+ SubstreamChannelParameters scp;
+
+ int sap_mode;
+
+ int N_prev;
+
+ uint8_t ms_used[16][128];
+ uint8_t sap_coeff_used[16][128];
+ int dpcm_alpha_q[16][128];
+
+ int delta_code_time;
+
+ int num_sec_lsf[16];
+ int num_sec[16];
+ uint8_t sfb_cb[16][128];
+ uint8_t sect_cb[16][128];
+ int sect_start[16][128];
+ int sect_end[16][128];
+ int sect_sfb_offset[16][128];
+
+ int16_t quant_spec[2048];
+ float scaled_spec[2048];
+ float spec_reord[2048];
+ int16_t offset2sfb[2048];
+ uint8_t offset2g[2048];
+ int win_offset[16];
+ DECLARE_ALIGNED(32, float, overlap)[4096];
+
+ int max_quant_idx[16][128];
+ int dpcm_sf[16][128];
+ int dpcm_snf[16][128];
+ int snf_data_exists;
+
+ float sf_gain[16][128];
+
+ int aspx_int_class;
+ int aspx_num_noise;
+ int aspx_num_noise_prev;
+ int aspx_num_rel_left;
+ int aspx_num_rel_right;
+ int aspx_num_env;
+ int aspx_num_env_prev;
+ int aspx_freq_res[32];
+ int aspx_var_bord_left;
+ int aspx_var_bord_right;
+ int aspx_rel_bord_left[4];
+ int aspx_rel_bord_right[4];
+ int aspx_tsg_ptr;
+ int aspx_tsg_ptr_prev;
+
+ int aspx_qmode_env;
+ int aspx_sig_delta_dir[8];
+ int aspx_noise_delta_dir[2];
+ int aspx_tna_mode[16];
+ int aspx_tna_mode_prev[16];
+ int aspx_add_harmonic[16];
+ int aspx_fic_used_in_sfb[16];
+ int aspx_tic_used_in_slot[16];
+ int aspx_xover_subband_offset;
+ int aspx_balance;
+
+ uint8_t atsg_freqres[32];
+ uint8_t atsg_freqres_prev[32];
+ int atsg_sig[32];
+ int atsg_noise[32];
+ int previous_stop_pos;
+
+ int num_sbg_master;
+ int sba;
+ int sbx;
+ int sbz;
+ int sbg_master[24];
+ int sbg_noise[6];
+ int sbg_sig_lowres[24];
+ int sbg_sig_highres[24];
+ int sbg_lim[32];
+ int sbg_patches[6];
+ int sbg_patch_num_sb[6];
+ int sbg_patch_start_sb[6];
+
+ int num_sb_aspx;
+ int num_sbg_noise;
+ int num_sbg_sig_highres;
+ int num_sbg_sig_lowres;
+ int num_sbg_sig[8];
+ int sbg_sig[8][24];
+ int num_sbg_patches;
+ int num_sbg_lim;
+
+ int aspx_data[2][32][64];
+
+ int qscf_prev[32][64]; // XXX
+ int qscf_sig_sbg[32][64]; // XXX
+ int qscf_sig_sbg_prev[32][64]; // XXX
+ int qscf_noise_sbg[32][64]; // XXX
+
+ float scf_sig_sbg[32][64]; // XXX
+ float scf_sig_sb[32][64]; // XXX
+ float scf_noise_sbg[32][64]; // XXX
+ float scf_noise_sb[32][64]; // XXX
+
+ float gain_vec[32];
+ float chirp_arr[6];
+ float chirp_arr_prev[6];
+ float est_sig_sb[32][64];
+ float sine_idx_sb[32][64];
+ float sine_idx_sb_prev[32][64];
+ float sine_area_sb[32][64];
+ float sine_lev_sb[32][64];
+ float noise_lev_sb[32][64];
+ float sig_gain_sb[32][64];
+ float max_sig_gain_sbg[32][64];
+ float max_sig_gain_sb[32][64];
+ float noise_lev_sb_lim[32][64];
+ float sig_gain_sb_lim[32][64];
+ float boost_fact_sbg[32][64];
+ float boost_fact_sb[32][64];
+ float sig_gain_sb_adj[42][64];
+ float noise_lev_sb_adj[42][64];
+ float sine_lev_sb_adj[42][64];
+
+ float qmf_sine[2][42][64];
+ int sine_idx[64][42];
+ int sine_idx_prev[64][42];
+
+ int acpl_interpolation_type;
+ int acpl_num_param_sets_cod;
+ int acpl_param_timeslot[2];
+ int acpl_data[11][16];
+
+ float pcm[2048];
+
+ DECLARE_ALIGNED(32, float, qmf_filt)[640];
+ DECLARE_ALIGNED(32, float, qsyn_filt)[1280];
+ DECLARE_ALIGNED(32, float, Q)[2][32][64];
+ DECLARE_ALIGNED(32, float, Q_prev)[2][32][64];
+ DECLARE_ALIGNED(32, float, Q_low)[2][42][64];
+ DECLARE_ALIGNED(32, float, Q_low_prev)[2][42][64];
+ DECLARE_ALIGNED(32, float, Q_low_ext)[2][42][64];
+ DECLARE_ALIGNED(32, float, Q_high)[2][42][64];
+ DECLARE_ALIGNED(32, float, cov)[64][3][3][2];
+ DECLARE_ALIGNED(32, float, alpha0)[64][2];
+ DECLARE_ALIGNED(32, float, alpha1)[64][2];
+ DECLARE_ALIGNED(32, float, Y)[2][42][64];
+ DECLARE_ALIGNED(32, float, Y_prev)[2][42][64];
+} SubstreamChannel;
+
+typedef struct Substream {
+ int codec_mode;
+
+ int aspx_quant_mode_env;
+ int aspx_start_freq;
+ int prev_aspx_start_freq;
+ int aspx_stop_freq;
+ int prev_aspx_stop_freq;
+ int aspx_master_freq_scale;
+ int prev_aspx_master_freq_scale;
+ int aspx_interpolation;
+ int aspx_preflat;
+ int aspx_limiter;
+ int aspx_noise_sbg;
+ int aspx_num_env_bits_fixfix;
+ int aspx_freq_res_mode;
+
+ int acpl_qmf_band;
+ int acpl_param_band;
+ int acpl_num_param_bands_id;
+ int acpl_quant_mode[2];
+
+ uint8_t mode_2ch;
+ uint8_t chel_matsel;
+
+ uint8_t compand_on[5];
+ int compand_avg;
+
+ int max_sfb_master;
+
+ uint8_t coding_config;
+ uint8_t mdct_stereo_proc[2];
+ float matrix_stereo[16][128][2][2];
+ float alpha_q[16][128];
+
+ int spec_frontend_l;
+ int spec_frontend_r;
+ int spec_frontend_m;
+ int spec_frontend_s;
+
+ SubstreamChannel ssch[9];
+} Substream;
+
+typedef struct PresentationSubstreamInfo {
+ int alternative;
+ int pres_ndot;
+ int substream_index;
+} PresentationSubstreamInfo;
+
+typedef struct Metadata {
+ int dialnorm_bits;
+ int pre_dmixtyp_2ch;
+ int phase90_info_2ch;
+ int loro_center_mixgain;
+ int loro_surround_mixgain;
+ int loro_dmx_loud_corr;
+ int ltrt_center_mixgain;
+ int ltrt_surround_mixgain;
+ int ltrt_dmx_loud_corr;
+ int lfe_mixgain;
+ int preferred_dmx_method;
+ int pre_dmixtyp_5ch;
+ int pre_upmixtyp_5ch;
+ int pre_upmixtyp_3_4;
+ int pre_upmixtyp_3_2_2;
+ int phase90_info_mc;
+ int surround_attenuation_known;
+ int lfe_attenuation_known;
+ int dc_block_on;
+
+ int loudness_version;
+ int loud_prac_type;
+ int dialgate_prac_type;
+ int loudcorr_type;
+ int loudrelgat;
+ int loudspchgat;
+ int loudstrm3s;
+ int max_loudstrm3s;
+ int truepk;
+ int max_truepk;
+ int prgmbndy;
+ int end_or_start;
+ int prgmbndy_offset;
+ int lra;
+ int lra_prac_type;
+ int loudmntry;
+ int max_loudmntry;
+
+ int drc_decoder_nr_modes;
+ int drc_eac3_profile;
+} Metadata;
+
+typedef struct SubstreamInfo {
+ int sus_ver;
+ int channel_mode;
+ int substream_index;
+ int sf_multiplier;
+ int bitrate_indicator;
+ int add_ch_base;
+ int iframe[4];
+ int back_channels_present;
+ int centre_present;
+ int top_channels_present;
+ Metadata meta;
+} SubstreamInfo;
+
+typedef struct SubstreamGroupInfo {
+ int channel_coded;
+ int group_index;
+} SubstreamGroupInfo;
+
+typedef struct PresentationInfo {
+ int single_substream;
+ int enable_presentation;
+ int presentation_config;
+ int presentation_version;
+ int add_emdf_substreams;
+ int n_add_emdf_substreams;
+ int n_substream_groups;
+ int mdcompat;
+ int presentation_id;
+ int multiplier;
+ int multiplier_bit;
+ int pre_virtualized;
+ int frame_rate_factor;
+ int frame_rate_fraction;
+ int multi_pid;
+ int hsf_ext;
+ EMDFInfo emdf[32];
+ PresentationSubstreamInfo psinfo;
+ SubstreamInfo ssinfo;
+} PresentationInfo;
+
+typedef struct AC4DecodeContext {
+ AVClass *class; ///< class for AVOptions
+ AVCodecContext *avctx; ///< parent context
+ AVFloatDSPContext *fdsp;
+ GetBitContext gbc; ///< bitstream reader
+
+ int version;
+ int sequence_counter;
+ int sequence_counter_prev;
+ int wait_frames;
+ int nb_wait_frames;
+ int fs_index;
+ int frame_rate_index;
+ int frame_len_base;
+ int frame_len_base_idx;
+ AVRational resampling_ratio;
+ int num_qmf_timeslots;
+ int num_aspx_timeslots;
+ int num_ts_in_ats;
+ int ts_offset_hfgen;
+ int transform_length;
+ int iframe_global;
+ int have_iframe;
+ int nb_presentations;
+ int payload_base;
+ int short_program_id;
+ int nb_substreams;
+ int total_groups;
+ int substream_size[32];
+ int substream_type[32];
+
+ DECLARE_ALIGNED(32, float, winl)[2048];
+ DECLARE_ALIGNED(32, float, winr)[2048];
+
+ SubstreamGroupInfo ssgroup[8];
+ PresentationInfo pinfo[8];
+ Substream substream;
+
+ av_tx_fn tx_fn[8][5];
+ AVTXContext *tx_ctx[8][5];
+
+ DECLARE_ALIGNED(32, float, kbd_window)[8][5][2048];
+
+ float quant_lut[8192];
+
+ DECLARE_ALIGNED(32, float, cos_atab)[64][128];
+ DECLARE_ALIGNED(32, float, sin_atab)[64][128];
+ DECLARE_ALIGNED(32, float, cos_stab)[128][64];
+ DECLARE_ALIGNED(32, float, sin_stab)[128][64];
+} AC4DecodeContext;
+
+enum ACPLMode {
+ ACPL_FULL,
+ ACPL_PARTIAL,
+};
+
+enum SubstreamType {
+ ST_SUBSTREAM,
+ ST_PRESENTATION,
+};
+
+enum StereoMode {
+ SM_LEVEL,
+ SM_BALANCE,
+};
+
+enum DataType {
+ DT_SIGNAL,
+ DT_NOISE,
+};
+
+enum SpectralFrontend {
+ SF_ASF,
+ SF_SSF,
+};
+
+enum HCBType {
+ F0,
+ DF,
+ DT,
+};
+
+enum CodecMode {
+ CM_SIMPLE,
+ CM_ASPX,
+ CM_ASPX_ACPL_1,
+ CM_ASPX_ACPL_2,
+ CM_ASPX_ACPL_3,
+};
+
+enum IntervalClass {
+ FIXFIX,
+ FIXVAR,
+ VARFIX,
+ VARVAR,
+};
+
+enum ACPLDataType {
+ ALPHA1,
+ ALPHA2,
+ BETA1,
+ BETA2,
+ BETA3,
+ GAMMA1,
+ GAMMA2,
+ GAMMA3,
+ GAMMA4,
+ GAMMA5,
+ GAMMA6,
+};
+
+static const AVRational resampling_ratios[] = {
+ {25025, 24000},
+ {25, 24},
+ {15, 16},
+ {25025, 24000},
+ {25, 24},
+ {25025, 24000},
+ {25, 24},
+ {15, 16},
+ {25025, 24000},
+ {25, 24},
+ {15, 16},
+ {25025, 24000},
+ {25, 24},
+ {1, 1},
+ {1, 1},
+ {1, 1},
+};
+
+static const uint8_t channel_mode_nb_channels[] = {
+ 1, 2, 3, 5, 6, 7, 8, 7, 8, 7, 8, 11, 12, 13, 14, 24, 0
+};
+
+static const uint64_t channel_mode_layouts[] = {
+ AV_CH_LAYOUT_MONO,
+ AV_CH_LAYOUT_STEREO,
+ AV_CH_LAYOUT_SURROUND,
+ AV_CH_LAYOUT_5POINT0,
+ AV_CH_LAYOUT_5POINT1,
+ AV_CH_LAYOUT_7POINT0,
+ AV_CH_LAYOUT_7POINT1,
+ AV_CH_LAYOUT_7POINT0_FRONT,
+ AV_CH_LAYOUT_7POINT0_FRONT|AV_CH_LOW_FREQUENCY,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+};
+
+static VLC channel_mode_vlc;
+static VLC bitrate_indicator_vlc;
+static VLC scale_factors_vlc;
+static VLC snf_vlc;
+static VLC asf_codebook_vlc[11];
+static VLC acpl_codebook_vlc[4][2][3];
+static VLC aspx_int_class_vlc;
+static VLC aspx_codebook_signal_vlc[2][2][3];
+static VLC aspx_codebook_noise_vlc[2][3];
+
+static av_cold int ac4_decode_init(AVCodecContext *avctx)
+{
+ AC4DecodeContext *s = avctx->priv_data;
+ int ret;
+
+ s->avctx = avctx;
+
+ avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
+
+ INIT_VLC_STATIC(&channel_mode_vlc, 9, sizeof(channel_mode_bits),
+ channel_mode_bits, 1, 1, channel_mode_codes, 2, 2, 512);
+ INIT_VLC_STATIC(&bitrate_indicator_vlc, 5, sizeof(bitrate_indicator_bits),
+ bitrate_indicator_bits, 1, 1, bitrate_indicator_codes, 1, 1, 32);
+ INIT_VLC_STATIC(&scale_factors_vlc, 9, sizeof(scale_factors_bits),
+ scale_factors_bits, 1, 1, scale_factors_codes, 1, 1, 850);
+ INIT_VLC_STATIC(&snf_vlc, 6, sizeof(snf_bits),
+ snf_bits, 1, 1, snf_codes, 1, 1, 70);
+
+ INIT_VLC_STATIC(&asf_codebook_vlc[0], 9, sizeof(asf_codebook_1_bits),
+ asf_codebook_1_bits, 1, 1, asf_codebook_1_codes, 1, 1, 542);
+ INIT_VLC_STATIC(&asf_codebook_vlc[1], 9, sizeof(asf_codebook_2_bits),
+ asf_codebook_2_bits, 1, 1, asf_codebook_2_codes, 1, 1, 512);
+ INIT_VLC_STATIC(&asf_codebook_vlc[2], 9, sizeof(asf_codebook_3_bits),
+ asf_codebook_3_bits, 1, 1, asf_codebook_3_codes, 1, 1, 612);
+ INIT_VLC_STATIC(&asf_codebook_vlc[3], 9, sizeof(asf_codebook_4_bits),
+ asf_codebook_4_bits, 1, 1, asf_codebook_4_codes, 1, 1, 544);
+ INIT_VLC_STATIC(&asf_codebook_vlc[4], 9, sizeof(asf_codebook_5_bits),
+ asf_codebook_5_bits, 1, 1, asf_codebook_5_codes, 1, 1, 576);
+ INIT_VLC_STATIC(&asf_codebook_vlc[5], 9, sizeof(asf_codebook_6_bits),
+ asf_codebook_6_bits, 1, 1, asf_codebook_6_codes, 1, 1, 546);
+ INIT_VLC_STATIC(&asf_codebook_vlc[6], 9, sizeof(asf_codebook_7_bits),
+ asf_codebook_7_bits, 1, 1, asf_codebook_7_codes, 1, 1, 542);
+ INIT_VLC_STATIC(&asf_codebook_vlc[7], 9, sizeof(asf_codebook_8_bits),
+ asf_codebook_8_bits, 1, 1, asf_codebook_8_codes, 1, 1, 522);
+ INIT_VLC_STATIC(&asf_codebook_vlc[8], 9, sizeof(asf_codebook_9_bits),
+ asf_codebook_9_bits, 1, 1, asf_codebook_9_codes, 1, 1, 670);
+ INIT_VLC_STATIC(&asf_codebook_vlc[9], 9, sizeof(asf_codebook_10_bits),
+ asf_codebook_10_bits, 1, 1, asf_codebook_10_codes, 1, 1, 604);
+ INIT_VLC_STATIC(&asf_codebook_vlc[10], 9, sizeof(asf_codebook_11_bits),
+ asf_codebook_11_bits, 1, 1, asf_codebook_11_codes, 1, 1, 674);
+
+ INIT_VLC_STATIC(&aspx_int_class_vlc, 5, sizeof(aspx_int_class_bits),
+ aspx_int_class_bits, 1, 1, aspx_int_class_codes, 1, 1, 32);
+
+ INIT_VLC_STATIC(&aspx_codebook_signal_vlc[0][0][0], 9, sizeof(aspx_hcb_env_level_15_f0_bits),
+ aspx_hcb_env_level_15_f0_bits, 1, 1, aspx_hcb_env_level_15_f0_codes, 4, 4, 1024);
+ INIT_VLC_STATIC(&aspx_codebook_signal_vlc[0][0][1], 9, sizeof(aspx_hcb_env_level_15_df_bits),
+ aspx_hcb_env_level_15_df_bits, 1, 1, aspx_hcb_env_level_15_df_codes, 4, 4, 1888);
+ INIT_VLC_STATIC(&aspx_codebook_signal_vlc[0][0][2], 9, sizeof(aspx_hcb_env_level_15_dt_bits),
+ aspx_hcb_env_level_15_dt_bits, 1, 1, aspx_hcb_env_level_15_dt_codes, 4, 4, 1368);
+
+ INIT_VLC_STATIC(&aspx_codebook_signal_vlc[0][1][0], 9, sizeof(aspx_hcb_env_level_30_f0_bits),
+ aspx_hcb_env_level_30_f0_bits, 1, 1, aspx_hcb_env_level_30_f0_codes, 4, 4, 772);
+ INIT_VLC_STATIC(&aspx_codebook_signal_vlc[0][1][1], 9, sizeof(aspx_hcb_env_level_30_df_bits),
+ aspx_hcb_env_level_30_df_bits, 1, 1, aspx_hcb_env_level_30_df_codes, 4, 4, 1624);
+ INIT_VLC_STATIC(&aspx_codebook_signal_vlc[0][1][2], 9, sizeof(aspx_hcb_env_level_30_dt_bits),
+ aspx_hcb_env_level_30_dt_bits, 1, 1, aspx_hcb_env_level_30_dt_codes, 4, 4, 1598);
+
+ INIT_VLC_STATIC(&aspx_codebook_signal_vlc[1][0][0], 9, sizeof(aspx_hcb_env_balance_15_f0_bits),
+ aspx_hcb_env_balance_15_f0_bits, 1, 1, aspx_hcb_env_balance_15_f0_codes, 4, 4, 644);
+ INIT_VLC_STATIC(&aspx_codebook_signal_vlc[1][0][1], 9, sizeof(aspx_hcb_env_balance_15_df_bits),
+ aspx_hcb_env_balance_15_df_bits, 1, 1, aspx_hcb_env_balance_15_df_codes, 4, 4, 1056);
+ INIT_VLC_STATIC(&aspx_codebook_signal_vlc[1][0][2], 9, sizeof(aspx_hcb_env_balance_15_dt_bits),
+ aspx_hcb_env_balance_15_dt_bits, 1, 1, aspx_hcb_env_balance_15_dt_codes, 4, 4, 616);
+
+ INIT_VLC_STATIC(&aspx_codebook_signal_vlc[1][1][0], 9, sizeof(aspx_hcb_env_balance_30_f0_bits),
+ aspx_hcb_env_balance_30_f0_bits, 1, 1, aspx_hcb_env_balance_30_f0_codes, 2, 2, 520);
+ INIT_VLC_STATIC(&aspx_codebook_signal_vlc[1][1][1], 9, sizeof(aspx_hcb_env_balance_30_df_bits),
+ aspx_hcb_env_balance_30_df_bits, 1, 1, aspx_hcb_env_balance_30_df_codes, 4, 4, 768);
+ INIT_VLC_STATIC(&aspx_codebook_signal_vlc[1][1][2], 9, sizeof(aspx_hcb_env_balance_30_dt_bits),
+ aspx_hcb_env_balance_30_dt_bits, 1, 1, aspx_hcb_env_balance_30_dt_codes, 2, 2, 576);
+
+ INIT_VLC_STATIC(&aspx_codebook_noise_vlc[0][0], 9, sizeof(aspx_hcb_noise_level_f0_bits),
+ aspx_hcb_noise_level_f0_bits, 1, 1, aspx_hcb_noise_level_f0_codes, 2, 2, 672);
+ INIT_VLC_STATIC(&aspx_codebook_noise_vlc[0][1], 9, sizeof(aspx_hcb_noise_level_df_bits),
+ aspx_hcb_noise_level_df_bits, 1, 1, aspx_hcb_noise_level_df_codes, 4, 4, 1024);
+ INIT_VLC_STATIC(&aspx_codebook_noise_vlc[0][2], 9, sizeof(aspx_hcb_noise_level_dt_bits),
+ aspx_hcb_noise_level_dt_bits, 1, 1, aspx_hcb_noise_level_dt_codes, 2, 2, 768);
+
+ INIT_VLC_STATIC(&aspx_codebook_noise_vlc[1][0], 9, sizeof(aspx_hcb_noise_balance_f0_bits),
+ aspx_hcb_noise_balance_f0_bits, 1, 1, aspx_hcb_noise_balance_f0_codes, 2, 2, 516);
+ INIT_VLC_STATIC(&aspx_codebook_noise_vlc[1][1], 9, sizeof(aspx_hcb_noise_balance_df_bits),
+ aspx_hcb_noise_balance_df_bits, 1, 1, aspx_hcb_noise_balance_df_codes, 2, 2, 536);
+ INIT_VLC_STATIC(&aspx_codebook_noise_vlc[1][2], 9, sizeof(aspx_hcb_noise_balance_dt_bits),
+ aspx_hcb_noise_balance_dt_bits, 1, 1, aspx_hcb_noise_balance_dt_codes, 2, 2, 530);
+
+ INIT_VLC_STATIC(&acpl_codebook_vlc[0][1][0], 9, sizeof(acpl_hcb_alpha_coarse_f0_bits),
+ acpl_hcb_alpha_coarse_f0_bits, 1, 1, acpl_hcb_alpha_coarse_f0_codes, 2, 2, 516);
+ INIT_VLC_STATIC(&acpl_codebook_vlc[0][1][1], 9, sizeof(acpl_hcb_alpha_coarse_df_bits),
+ acpl_hcb_alpha_coarse_df_bits, 1, 1, acpl_hcb_alpha_coarse_df_codes, 4, 4, 1032);
+ INIT_VLC_STATIC(&acpl_codebook_vlc[0][1][2], 9, sizeof(acpl_hcb_alpha_coarse_dt_bits),
+ acpl_hcb_alpha_coarse_dt_bits, 1, 1, acpl_hcb_alpha_coarse_dt_codes, 4, 4, 642);
+
+ INIT_VLC_STATIC(&acpl_codebook_vlc[0][0][0], 9, sizeof(acpl_hcb_alpha_fine_f0_bits),
+ acpl_hcb_alpha_fine_f0_bits, 1, 1, acpl_hcb_alpha_fine_f0_codes, 2, 2, 530);
+ INIT_VLC_STATIC(&acpl_codebook_vlc[0][0][1], 9, sizeof(acpl_hcb_alpha_fine_df_bits),
+ acpl_hcb_alpha_fine_df_bits, 1, 1, acpl_hcb_alpha_fine_df_codes, 4, 4, 1176);
+ INIT_VLC_STATIC(&acpl_codebook_vlc[0][0][2], 9, sizeof(acpl_hcb_alpha_fine_dt_bits),
+ acpl_hcb_alpha_fine_dt_bits, 1, 1, acpl_hcb_alpha_fine_dt_codes, 4, 4, 1158);
+
+ INIT_VLC_STATIC(&acpl_codebook_vlc[1][1][0], 9, sizeof(acpl_hcb_beta_coarse_f0_bits),
+ acpl_hcb_beta_coarse_f0_bits, 1, 1, acpl_hcb_beta_coarse_f0_codes, 1, 1, 512);
+ INIT_VLC_STATIC(&acpl_codebook_vlc[1][1][1], 9, sizeof(acpl_hcb_beta_coarse_df_bits),
+ acpl_hcb_beta_coarse_df_bits, 1, 1, acpl_hcb_beta_coarse_df_codes, 1, 1, 512);
+ INIT_VLC_STATIC(&acpl_codebook_vlc[1][1][2], 9, sizeof(acpl_hcb_beta_coarse_dt_bits),
+ acpl_hcb_beta_coarse_dt_bits, 1, 1, acpl_hcb_beta_coarse_dt_codes, 1, 1, 512);
+
+ INIT_VLC_STATIC(&acpl_codebook_vlc[1][0][0], 9, sizeof(acpl_hcb_beta_fine_f0_bits),
+ acpl_hcb_beta_fine_f0_bits, 1, 1, acpl_hcb_beta_fine_f0_codes, 1, 1, 512);
+ INIT_VLC_STATIC(&acpl_codebook_vlc[1][0][1], 9, sizeof(acpl_hcb_beta_fine_df_bits),
+ acpl_hcb_beta_fine_df_bits, 1, 1, acpl_hcb_beta_fine_df_codes, 4, 4, 528);
+ INIT_VLC_STATIC(&acpl_codebook_vlc[1][0][2], 9, sizeof(acpl_hcb_beta_fine_dt_bits),
+ acpl_hcb_beta_fine_dt_bits, 1, 1, acpl_hcb_beta_fine_dt_codes, 4, 4, 576);
+
+ INIT_VLC_STATIC(&acpl_codebook_vlc[2][1][0], 9, sizeof(acpl_hcb_beta3_coarse_f0_bits),
+ acpl_hcb_beta3_coarse_f0_bits, 1, 1, acpl_hcb_beta3_coarse_f0_codes, 1, 1, 512);
+ INIT_VLC_STATIC(&acpl_codebook_vlc[2][1][1], 9, sizeof(acpl_hcb_beta3_coarse_df_bits),
+ acpl_hcb_beta3_coarse_df_bits, 1, 1, acpl_hcb_beta3_coarse_df_codes, 4, 4, 528);
+ INIT_VLC_STATIC(&acpl_codebook_vlc[2][1][2], 9, sizeof(acpl_hcb_beta3_coarse_dt_bits),
+ acpl_hcb_beta3_coarse_dt_bits, 1, 1, acpl_hcb_beta3_coarse_dt_codes, 2, 2, 576);
+
+ INIT_VLC_STATIC(&acpl_codebook_vlc[2][0][0], 9, sizeof(acpl_hcb_beta3_fine_f0_bits),
+ acpl_hcb_beta3_fine_f0_bits, 1, 1, acpl_hcb_beta3_fine_f0_codes, 1, 1, 512);
+ INIT_VLC_STATIC(&acpl_codebook_vlc[2][0][1], 9, sizeof(acpl_hcb_beta3_fine_df_bits),
+ acpl_hcb_beta3_fine_df_bits, 1, 1, acpl_hcb_beta3_fine_df_codes, 4, 4, 580);
+ INIT_VLC_STATIC(&acpl_codebook_vlc[2][0][2], 9, sizeof(acpl_hcb_beta3_fine_dt_bits),
+ acpl_hcb_beta3_fine_dt_bits, 1, 1, acpl_hcb_beta3_fine_dt_codes, 4, 4, 768);
+
+ INIT_VLC_STATIC(&acpl_codebook_vlc[3][1][0], 9, sizeof(acpl_hcb_gamma_coarse_f0_bits),
+ acpl_hcb_gamma_coarse_f0_bits, 1, 1, acpl_hcb_gamma_coarse_f0_codes, 2, 2, 528);
+ INIT_VLC_STATIC(&acpl_codebook_vlc[3][1][1], 9, sizeof(acpl_hcb_gamma_coarse_df_bits),
+ acpl_hcb_gamma_coarse_df_bits, 1, 1, acpl_hcb_gamma_coarse_df_codes, 4, 4, 644);
+ INIT_VLC_STATIC(&acpl_codebook_vlc[3][1][2], 9, sizeof(acpl_hcb_gamma_coarse_dt_bits),
+ acpl_hcb_gamma_coarse_dt_bits, 1, 1, acpl_hcb_gamma_coarse_dt_codes, 4, 4, 896);
+
+ INIT_VLC_STATIC(&acpl_codebook_vlc[3][0][0], 9, sizeof(acpl_hcb_gamma_fine_f0_bits),
+ acpl_hcb_gamma_fine_f0_bits, 1, 1, acpl_hcb_gamma_fine_f0_codes, 4, 4, 544);
+ INIT_VLC_STATIC(&acpl_codebook_vlc[3][0][1], 9, sizeof(acpl_hcb_gamma_fine_df_bits),
+ acpl_hcb_gamma_fine_df_bits, 1, 1, acpl_hcb_gamma_fine_df_codes, 4, 4, 1026);
+ INIT_VLC_STATIC(&acpl_codebook_vlc[3][0][2], 9, sizeof(acpl_hcb_gamma_fine_dt_bits),
+ acpl_hcb_gamma_fine_dt_bits, 1, 1, acpl_hcb_gamma_fine_dt_codes, 4, 4, 1792);
+
+ for (int j = 0; j < 8; j++) {
+ const uint16_t *transf_lengths = transf_length_48khz[j];
+
+ for (int i = 0; i < 5; i++) {
+ int N_w = transf_lengths[i];
+ float alpha = kbd_window_alpha[j][i];
+ float scale = 1.f / (float)N_w;
+
+ if ((ret = av_tx_init(&s->tx_ctx[j][i], &s->tx_fn[j][i], AV_TX_FLOAT_MDCT, 1, N_w, &scale, 0)))
+ return ret;
+
+ ff_kbd_window_init(s->kbd_window[j][i], alpha, N_w);
+ }
+ }
+
+ for (int i = 0; i < 8192; i++)
+ s->quant_lut[i] = powf(i, 4.f / 3.f);
+
+ for (int i = 0; i < 64; i++) {
+ for (int n = 0; n < 128; n++) {
+ s->cos_atab[i][n] = cosf(M_PI/128*(i+0.5)*(2*n-1));
+ s->sin_atab[i][n] = sinf(M_PI/128*(i+0.5)*(2*n-1));
+ s->cos_stab[n][i] = cosf(M_PI/128*(i+0.5)*(2*n-255)) / 64;
+ s->sin_stab[n][i] = sinf(M_PI/128*(i+0.5)*(2*n-255)) / 64;
+ }
+ }
+
+ s->fdsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT);
+ if (!s->fdsp)
+ return AVERROR(ENOMEM);
+
+ return 0;
+}
+
+static int variable_bits(GetBitContext *gb, int bits)
+{
+ int value = 0;
+ int read_more;
+
+ do {
+ value += get_bits(gb, bits);
+ read_more = get_bits1(gb);
+ if (read_more) {
+ value <<= bits;
+ value += 1 << bits;
+ }
+ } while (read_more);
+
+ return value;
+}
+
+static int check_sequence(AC4DecodeContext *s)
+{
+ if (s->sequence_counter > 1020)
+ return AVERROR_INVALIDDATA;
+
+ if (s->sequence_counter == s->sequence_counter_prev + 1)
+ return 0;
+
+ if (s->sequence_counter != 0 && s->sequence_counter_prev == 0)
+ return 0;
+
+ if (s->sequence_counter == 1 && s->sequence_counter_prev == 1020)
+ return 0;
+
+ if (s->sequence_counter == 0 && s->sequence_counter_prev == 0)
+ return 0;
+
+ return AVERROR_INVALIDDATA;
+}
+
+static int frame_rate_multiply_info(AC4DecodeContext *s, PresentationInfo *p)
+{
+ GetBitContext *gb = &s->gbc;
+
+ p->multiplier_bit = 0;
+
+ switch (s->frame_rate_index) {
+ case 2:
+ case 3:
+ case 4:
+ p->multiplier = get_bits1(gb);
+ if (p->multiplier)
+ p->multiplier_bit = get_bits1(gb);
+ p->frame_rate_factor = p->multiplier ? (p->multiplier_bit ? 4 : 2) : 1;
+ break;
+ case 0:
+ case 1:
+ case 7:
+ case 8:
+ case 9:
+ p->multiplier = get_bits1(gb);
+ p->frame_rate_factor = p->multiplier ? 2 : 1;
+ break;
+ default:
+ p->frame_rate_factor = 1;
+ break;
+ }
+
+ return 0;
+}
+
+static int emdf_payloads_substream_info(AC4DecodeContext *s, EMDFInfo *e)
+{
+ GetBitContext *gb = &s->gbc;
+
+ e->substream_index = get_bits(gb, 2);
+ if (e->substream_index == 3)
+ e->substream_index += variable_bits(gb, 2);
+
+ return 0;
+}
+
+static int emdf_protection(AC4DecodeContext *s, EMDFInfo *e)
+{
+ GetBitContext *gb = &s->gbc;
+ int first, second;
+
+ first = get_bits(gb, 2);
+ second = get_bits(gb, 2);
+
+ switch (first) {
+ case 0:
+ break;
+ case 1:
+ skip_bits(gb, 8);
+ break;
+ case 2:
+ skip_bits_long(gb, 32);
+ break;
+ case 3:
+ skip_bits_long(gb, 128);
+ break;
+ }
+
+ switch (second) {
+ case 0:
+ break;
+ case 1:
+ skip_bits(gb, 8);
+ break;
+ case 2:
+ skip_bits_long(gb, 32);
+ break;
+ case 3:
+ skip_bits_long(gb, 128);
+ break;
+ }
+
+ return 0;
+}
+
+static int emdf_info(AC4DecodeContext *s, EMDFInfo *e)
+{
+ GetBitContext *gb = &s->gbc;
+
+ e->version = get_bits(gb, 2);
+ if (e->version == 3)
+ e->version += variable_bits(gb, 2);
+ e->key_id = get_bits(gb, 3);
+ if (e->key_id == 7)
+ e->key_id += variable_bits(gb, 3);
+
+ if (get_bits1(gb))
+ emdf_payloads_substream_info(s, e);
+
+ emdf_protection(s, e);
+
+ return 0;
+}
+
+static int content_type(AC4DecodeContext *s, PresentationInfo *p)
+{
+ GetBitContext *gb = &s->gbc;
+
+ skip_bits(gb, 3);
+ if (get_bits1(gb)) {
+ if (get_bits1(gb)) {
+ skip_bits(gb, 1);
+ skip_bits(gb, 16);
+ } else {
+ int language_tag_bytes = get_bits(gb, 6);
+
+ skip_bits_long(gb, 8 * language_tag_bytes);
+ }
+ }
+
+ return 0;
+}
+
+static int ac4_substream_info(AC4DecodeContext *s, PresentationInfo *p,
+ SubstreamInfo *ssi)
+{
+ GetBitContext *gb = &s->gbc;
+
+ ssi->sus_ver = 0;
+ ssi->channel_mode = get_vlc2(gb, channel_mode_vlc.table, channel_mode_vlc.bits, 1);
+ if (ssi->channel_mode < 0)
+ return AVERROR_INVALIDDATA;
+
+ if (ssi->channel_mode == 16)
+ ssi->channel_mode += variable_bits(gb, 2);
+
+ if (s->fs_index == 1 && get_bits1(gb))
+ ssi->sf_multiplier = 1 + get_bits1(gb);
+ av_log(s->avctx, AV_LOG_DEBUG, "sf_multiplier: %d\n", ssi->sf_multiplier);
+
+ if (get_bits1(gb))
+ ssi->bitrate_indicator = get_vlc2(gb, bitrate_indicator_vlc.table, bitrate_indicator_vlc.bits, 1);
+
+ if (ssi->channel_mode == 7 ||
+ ssi->channel_mode == 8 ||
+ ssi->channel_mode == 9 ||
+ ssi->channel_mode == 10) {
+ ssi->add_ch_base = get_bits1(gb);
+ }
+
+ if (get_bits1(gb))
+ content_type(s, p);
+
+ for (int i = 0; i < p->frame_rate_factor; i++)
+ ssi->iframe[i] = get_bits1(gb);
+
+ ssi->substream_index = get_bits(gb, 2);
+ if (ssi->substream_index == 3)
+ ssi->substream_index += variable_bits(gb, 2);
+ s->substream_type[ssi->substream_index] = ST_SUBSTREAM;
+ av_log(s->avctx, AV_LOG_DEBUG, "substream index: %d\n", ssi->substream_index);
+
+ return 0;
+}
+
+static int presentation_config_ext_info(AC4DecodeContext *s)
+{
+ GetBitContext *gb = &s->gbc;
+ int n_skip_bytes;
+
+ n_skip_bytes = get_bits(gb, 5);
+ if (get_bits1(gb))
+ n_skip_bytes += variable_bits(gb, 2) << 5;
+
+ skip_bits_long(gb, 8 * n_skip_bytes);
+
+ return 0;
+}
+
+static int ac4_presentation_info(AC4DecodeContext *s, PresentationInfo *p)
+{
+ GetBitContext *gb = &s->gbc;
+ int ret;
+
+ p->single_substream = get_bits1(gb);
+ if (p->single_substream != 1) {
+ p->presentation_config = get_bits(gb, 3);
+ if (p->presentation_config == 0x7) {
+ p->presentation_config += variable_bits(gb, 2);
+ }
+ }
+
+ p->presentation_version = get_unary(gb, 0, 31);
+
+ p->add_emdf_substreams = 0;
+ if (p->single_substream != 1 && p->presentation_config == 6) {
+ p->add_emdf_substreams = 1;
+ } else {
+ p->mdcompat = get_bits(gb, 3);
+
+ if (get_bits1(gb))
+ p->presentation_id = variable_bits(gb, 2);
+
+ frame_rate_multiply_info(s, p);
+ emdf_info(s, &p->emdf[0]);
+
+ if (p->single_substream == 1) {
+ ret = ac4_substream_info(s, p, &p->ssinfo);
+ if (ret < 0)
+ return ret;
+ } else {
+ p->hsf_ext = get_bits1(gb);
+ switch (p->presentation_config) {
+ case 0:
+ av_assert0(0);
+ ret = ac4_substream_info(s, p, &p->ssinfo);
+ if (ret < 0)
+ return ret;
+ break;
+ default:
+ presentation_config_ext_info(s);
+ }
+ }
+
+ p->pre_virtualized = get_bits1(gb);
+ p->add_emdf_substreams = get_bits1(gb);
+ }
+
+ if (p->add_emdf_substreams) {
+ p->n_add_emdf_substreams = get_bits(gb, 2);
+ if (p->n_add_emdf_substreams == 0)
+ p->n_add_emdf_substreams = variable_bits(gb, 2) + 4;
+
+ for (int i = 0; i < p->n_add_emdf_substreams; i++)
+ emdf_info(s, &p->emdf[i]);
+ }
+
+ return 0;
+}
+
+static int substream_index_table(AC4DecodeContext *s)
+{
+ GetBitContext *gb = &s->gbc;
+ int size_present;
+
+ s->nb_substreams = get_bits(gb, 2);
+ if (s->nb_substreams == 0)
+ s->nb_substreams = variable_bits(gb, 2) + 4;
+
+ av_log(s->avctx, AV_LOG_DEBUG, "nb_substreams: %d\n", s->nb_substreams);
+
+ if (s->nb_substreams == 1) {
+ size_present = get_bits1(gb);
+ } else {
+ size_present = 1;
+ }
+
+ if (size_present) {
+ for (int i = 0; i < s->nb_substreams; i++) {
+ int more_bits = get_bits1(gb);
+
+ s->substream_size[i] = get_bits(gb, 10);
+ if (more_bits)
+ s->substream_size[i] += variable_bits(gb, 2) << 10;
+ av_log(s->avctx, AV_LOG_DEBUG, "substream[%d] size: %d\n", i, s->substream_size[i]);
+ }
+ }
+
+ return 0;
+}
+
+static int presentation_substream_info(AC4DecodeContext *s, PresentationSubstreamInfo *psi)
+{
+ GetBitContext *gb = &s->gbc;
+
+ psi->alternative = get_bits1(gb);
+ psi->pres_ndot = get_bits1(gb);
+ psi->substream_index = get_bits(gb, 2);
+ if (psi->substream_index == 3)
+ psi->substream_index += variable_bits(gb, 2);
+ s->substream_type[psi->substream_index] = ST_PRESENTATION;
+ av_log(s->avctx, AV_LOG_DEBUG, "presentation substream index: %d\n", psi->substream_index);
+
+ return 0;
+}
+
+static int frame_rate_fractions_info(AC4DecodeContext *s, PresentationInfo *p)
+{
+ GetBitContext *gb = &s->gbc;
+
+ p->frame_rate_fraction = 1;
+ if (s->frame_rate_index >= 5 && s->frame_rate_index <= 9) {
+ if (p->frame_rate_factor == 1) {
+ if (get_bits1(gb))
+ p->frame_rate_fraction = 2;
+ }
+ }
+
+ if (s->frame_rate_index >= 10 && s->frame_rate_index <= 12) {
+ if (get_bits1(gb)) {
+ if (get_bits1(gb))
+ p->frame_rate_fraction = 4;
+ else
+ p->frame_rate_fraction = 2;
+ }
+ }
+
+ return 0;
+}
+
+static int ac4_substream_info_chan(AC4DecodeContext *s, PresentationInfo *p,
+ SubstreamInfo *ssi, int substreams_present,
+ int sus_ver)
+{
+ GetBitContext *gb = &s->gbc;
+
+ ssi->sus_ver = sus_ver;
+ ssi->channel_mode = get_vlc2(gb, channel_mode_vlc.table, channel_mode_vlc.bits, 3);
+ if (ssi->channel_mode < 0)
+ return AVERROR_INVALIDDATA;
+
+ if (ssi->channel_mode == 16)
+ ssi->channel_mode += variable_bits(gb, 2);
+
+ if (ssi->channel_mode == 11 ||
+ ssi->channel_mode == 12 ||
+ ssi->channel_mode == 13 ||
+ ssi->channel_mode == 14) {
+ ssi->back_channels_present = get_bits1(gb);
+ ssi->centre_present = get_bits1(gb);
+ ssi->top_channels_present = get_bits(gb, 2);
+ }
+
+ if (s->fs_index && get_bits1(gb))
+ ssi->sf_multiplier = 1 + get_bits1(gb);
+ av_log(s->avctx, AV_LOG_DEBUG, "sf_multiplier: %d\n", ssi->sf_multiplier);
+
+ if (get_bits1(gb))
+ ssi->bitrate_indicator = get_vlc2(gb, bitrate_indicator_vlc.table, bitrate_indicator_vlc.bits, 1);
+
+ if (ssi->channel_mode == 7 ||
+ ssi->channel_mode == 8 ||
+ ssi->channel_mode == 9 ||
+ ssi->channel_mode == 10)
+ ssi->add_ch_base = get_bits1(gb);
+
+ for (int i = 0; i < p->frame_rate_factor; i++)
+ ssi->iframe[i] = get_bits1(gb);
+
+ if (substreams_present) {
+ ssi->substream_index = get_bits(gb, 2);
+ if (ssi->substream_index == 3)
+ ssi->substream_index += variable_bits(gb, 2);
+ av_log(s->avctx, AV_LOG_DEBUG, "substream index: %d\n", ssi->substream_index);
+ }
+
+ return 0;
+}
+
+static int ac4_substream_group_info(AC4DecodeContext *s,
+ SubstreamGroupInfo *g,
+ PresentationInfo *p)
+{
+ GetBitContext *gb = &s->gbc;
+ int substreams_present;
+ int n_lf_substreams;
+ int hsf_ext;
+ int sus_ver;
+
+ substreams_present = get_bits1(gb);
+ hsf_ext = get_bits1(gb);
+ if (get_bits1(gb)) {
+ n_lf_substreams = 1;
+ } else {
+ n_lf_substreams = get_bits(gb, 2) + 2;
+ if (n_lf_substreams == 5)
+ n_lf_substreams += variable_bits(gb, 2);
+ }
+ g->channel_coded = get_bits1(gb);
+ if (g->channel_coded) {
+ for (int sus = 0; sus < n_lf_substreams; sus++) {
+ if (s->version == 1) {
+ sus_ver = get_bits1(gb);
+ } else {
+ sus_ver = 1;
+ }
+ ac4_substream_info_chan(s, p, &p->ssinfo, substreams_present, sus_ver);
+ if (hsf_ext)
+ av_assert0(0);
+ //ac4_hsf_ext_substream_info(substreams_present);
+ }
+ } else {
+ av_assert0(0);
+ //if (get_bits1(gb))
+ // oamd_substream_info(substreams_present);
+ //for (int sus = 0; sus < n_lf_substreams; sus++) {
+ // if (get_bits1(gb)) {
+ // ac4_substream_info_ajoc(substreams_present);
+ // if (hsf_ext) {
+ // ac4_hsf_ext_substream_info(substreams_present);
+ // }
+ // } else {
+ // ac4_substream_info_obj(substreams_present);
+ // if (hsf_ext)
+ // ac4_hsf_ext_substream_info(substreams_present);
+ // }
+ //}
+ }
+
+ if (get_bits1(gb))
+ content_type(s, NULL);
+
+ return 0;
+}
+
+static int ac4_sgi_specifier(AC4DecodeContext *s, PresentationInfo *p,
+ SubstreamGroupInfo *g)
+{
+ GetBitContext *gb = &s->gbc;
+
+ if (s->version == 1) {
+ av_assert0(0);
+ //ac4_substream_group_info(s);
+ } else {
+ g->group_index = get_bits(gb, 3);
+ if (g->group_index == 7)
+ g->group_index += variable_bits(gb, 2);
+ }
+
+ s->total_groups = FFMAX(s->total_groups, g->group_index);
+
+ return 0;
+}
+
+static int ac4_presentation_v1_info(AC4DecodeContext *s, PresentationInfo *p)
+{
+ GetBitContext *gb = &s->gbc;
+ int single_substream_group;
+
+ single_substream_group = get_bits1(gb);
+ if (single_substream_group != 1) {
+ p->presentation_config = get_bits(gb, 3);
+ if (p->presentation_config == 7)
+ p->presentation_config += variable_bits(gb, 2);
+ }
+ if (s->version != 1)
+ p->presentation_version = get_unary(gb, 0, 31);
+
+ if (single_substream_group != 1 && p->presentation_config == 6) {
+ p->add_emdf_substreams = 1;
+ } else {
+ if (s->version != 1)
+ p->mdcompat = get_bits(gb, 3);
+
+ if (get_bits1(gb))
+ p->presentation_id = variable_bits(gb, 2);
+
+ frame_rate_multiply_info(s, p);
+ frame_rate_fractions_info(s, p);
+ emdf_info(s, &p->emdf[0]);
+
+ if (get_bits1(gb))
+ p->enable_presentation = get_bits1(gb);
+
+ if (single_substream_group == 1) {
+ ac4_sgi_specifier(s, p, &s->ssgroup[0]);
+ p->n_substream_groups = 1;
+ } else {
+ p->multi_pid = get_bits1(gb);
+ switch (p->presentation_config) {
+ case 0:
+ /* Music and Effects + Dialogue */
+ ac4_sgi_specifier(s, p, &s->ssgroup[0]);
+ ac4_sgi_specifier(s, p, &s->ssgroup[1]);
+ p->n_substream_groups = 2;
+ break;
+ case 1:
+ /* Main + DE */
+ ac4_sgi_specifier(s, p, &s->ssgroup[0]);
+ ac4_sgi_specifier(s, p, &s->ssgroup[1]);
+ p->n_substream_groups = 1;
+ break;
+ case 2:
+ /* Main + Associated Audio */
+ ac4_sgi_specifier(s, p, &s->ssgroup[0]);
+ ac4_sgi_specifier(s, p, &s->ssgroup[1]);
+ p->n_substream_groups = 2;
+ break;
+ case 3:
+ /* Music and Effects + Dialogue + Associated Audio */
+ ac4_sgi_specifier(s, p, &s->ssgroup[0]);
+ ac4_sgi_specifier(s, p, &s->ssgroup[1]);
+ ac4_sgi_specifier(s, p, &s->ssgroup[2]);
+ p->n_substream_groups = 3;
+ break;
+ case 4:
+ /* Main + DE + Associated Audio */
+ ac4_sgi_specifier(s, p, &s->ssgroup[0]);
+ ac4_sgi_specifier(s, p, &s->ssgroup[1]);
+ ac4_sgi_specifier(s, p, &s->ssgroup[2]);
+ p->n_substream_groups = 2;
+ break;
+ case 5:
+ /* Arbitrary number of roles and substream groups */
+ p->n_substream_groups = get_bits(gb, 2) + 2;
+ if (p->n_substream_groups == 5)
+ p->n_substream_groups += variable_bits(gb, 2);
+
+ for (int sg = 0; sg < p->n_substream_groups; sg++)
+ ac4_sgi_specifier(s, p, &s->ssgroup[sg]);
+ break;
+ default:
+ /* EMDF and other data */
+ presentation_config_ext_info(s);
+ break;
+ }
+ }
+ p->pre_virtualized = get_bits1(gb);
+ p->add_emdf_substreams = get_bits1(gb);
+ presentation_substream_info(s, &p->psinfo);
+ }
+
+ if (p->add_emdf_substreams) {
+ p->n_add_emdf_substreams = get_bits(gb, 2);
+ if (p->n_add_emdf_substreams == 0)
+ p->n_add_emdf_substreams = variable_bits(gb, 2) + 4;
+ for (int i = 0; i < p->n_add_emdf_substreams; i++)
+ emdf_info(s, &p->emdf[i]);
+ }
+
+ return 0;
+}
+
+static int get_num_ts_in_ats(int frame_length)
+{
+ if (frame_length <= 2048 && frame_length >= 1536)
+ return 2;
+
+ return 1;
+}
+
+static int ac4_toc(AC4DecodeContext *s)
+{
+ GetBitContext *gb = &s->gbc;
+ int ret;
+
+ s->version = get_bits(gb, 2);
+ if (s->version == 3)
+ s->version += variable_bits(gb, 2);
+ av_log(s->avctx, AV_LOG_DEBUG, "bitstream version: %d\n", s->version);
+ s->sequence_counter_prev = s->sequence_counter;
+ s->sequence_counter = get_bits(gb, 10);
+ av_log(s->avctx, AV_LOG_DEBUG, "sequence counter: %d\n", s->sequence_counter);
+
+ s->wait_frames = get_bits1(gb);
+ if (s->wait_frames) {
+ s->nb_wait_frames = get_bits(gb, 3);
+ if (s->nb_wait_frames > 0)
+ skip_bits(gb, 2);
+ }
+
+ s->fs_index = get_bits1(gb);
+ s->frame_rate_index = get_bits(gb, 4);
+ av_log(s->avctx, AV_LOG_DEBUG, "frame_rate_index: %d\n", s->frame_rate_index);
+ s->frame_len_base = frame_len_base_48khz[s->frame_rate_index];
+ s->num_ts_in_ats = get_num_ts_in_ats(s->frame_len_base);
+ s->frame_len_base_idx = frame_len_base_idx_48khz[s->frame_rate_index];
+ av_log(s->avctx, AV_LOG_DEBUG, "frame_len_base: %d\n", s->frame_len_base);
+ s->resampling_ratio = resampling_ratios[s->frame_rate_index];
+ s->num_qmf_timeslots = s->frame_len_base / 64;
+ s->num_aspx_timeslots = s->num_qmf_timeslots / s->num_ts_in_ats;
+ s->ts_offset_hfgen = 3 * s->num_ts_in_ats;
+ s->iframe_global = get_bits1(gb);
+ if (s->iframe_global) {
+ s->have_iframe = 1;
+ } else {
+ ret = check_sequence(s);
+ if (ret < 0)
+ return ret;
+ }
+ if (get_bits1(gb)) {
+ s->nb_presentations = 1;
+ } else {
+ if (get_bits1(gb)) {
+ s->nb_presentations = 2 + variable_bits(gb, 2);
+ } else {
+ s->nb_presentations = 0;
+ }
+ }
+
+ s->payload_base = 0;
+ if (get_bits1(gb)) {
+ s->payload_base = get_bits(gb, 5) + 1;
+ if (s->payload_base == 0x20) {
+ s->payload_base += variable_bits(gb, 3);
+ }
+ }
+
+ av_log(s->avctx, AV_LOG_DEBUG, "presentations: %d\n", s->nb_presentations);
+
+ if (s->version <= 1) {
+ for (int i = 0; i < s->nb_presentations; i++) {
+ ret = ac4_presentation_info(s, &s->pinfo[i]);
+ if (ret < 0)
+ return ret;
+ }
+ } else {
+ if (get_bits1(gb)) {
+ s->short_program_id = get_bits(gb, 16);
+ if (get_bits1(gb)) {
+ skip_bits_long(gb, 16 * 8);
+ }
+ }
+
+ for (int i = 0; i < s->nb_presentations; i++) {
+ ret = ac4_presentation_v1_info(s, &s->pinfo[i]);
+ if (ret < 0)
+ return ret;
+ }
+
+ for (int i = 0; i <= s->total_groups && s->nb_presentations; i++) {
+ ret = ac4_substream_group_info(s, &s->ssgroup[i], &s->pinfo[0]);
+ if (ret < 0)
+ return ret;
+ }
+ }
+
+ substream_index_table(s);
+
+ align_get_bits(gb);
+
+ av_log(s->avctx, AV_LOG_DEBUG, "TOC size: %d\n", get_bits_count(gb) >> 3);
+
+ return 0;
+}
+
+static int sb_to_pb(int acpl_num_param_bands_id, int acpl_qmf_band)
+{
+ if (acpl_qmf_band >= 0 &&
+ acpl_qmf_band <= 8)
+ return qmf_subbands[acpl_qmf_band][acpl_num_param_bands_id];
+ if (acpl_qmf_band >= 9 &&
+ acpl_qmf_band <= 10)
+ return qmf_subbands[9][acpl_num_param_bands_id];
+ if (acpl_qmf_band >= 11 &&
+ acpl_qmf_band <= 13)
+ return qmf_subbands[10][acpl_num_param_bands_id];
+ if (acpl_qmf_band >= 14 &&
+ acpl_qmf_band <= 17)
+ return qmf_subbands[11][acpl_num_param_bands_id];
+ if (acpl_qmf_band >= 18 &&
+ acpl_qmf_band <= 22)
+ return qmf_subbands[12][acpl_num_param_bands_id];
+ if (acpl_qmf_band >= 23 &&
+ acpl_qmf_band <= 34)
+ return qmf_subbands[13][acpl_num_param_bands_id];
+ if (acpl_qmf_band >= 35 &&
+ acpl_qmf_band <= 63)
+ return qmf_subbands[14][acpl_num_param_bands_id];
+ return 0;
+}
+
+static int acpl_config_1ch(AC4DecodeContext *s, Substream *ss, int mode)
+{
+ GetBitContext *gb = &s->gbc;
+
+ ss->acpl_qmf_band = 0;
+ ss->acpl_param_band = 0;
+ ss->acpl_num_param_bands_id = get_bits(gb, 2);
+ ss->acpl_quant_mode[0] = get_bits1(gb);
+ if (mode == ACPL_PARTIAL) {
+ ss->acpl_qmf_band = get_bits(gb, 3) + 1;
+ ss->acpl_param_band = sb_to_pb(ss->acpl_num_param_bands_id, ss->acpl_qmf_band);
+ }
+
+ return 0;
+}
+
+static int acpl_config_2ch(AC4DecodeContext *s, Substream *ss)
+{
+ GetBitContext *gb = &s->gbc;
+
+ ss->acpl_qmf_band = 0;
+ ss->acpl_param_band = 0;
+ ss->acpl_num_param_bands_id = get_bits(gb, 2);
+ ss->acpl_quant_mode[0] = get_bits1(gb);
+ ss->acpl_quant_mode[1] = get_bits1(gb);
+
+ return 0;
+}
+
+static int aspx_config(AC4DecodeContext *s, Substream *ss)
+{
+ GetBitContext *gb = &s->gbc;
+
+ ss->aspx_quant_mode_env = get_bits1(gb);
+ ss->prev_aspx_start_freq = ss->aspx_start_freq;
+ ss->aspx_start_freq = get_bits(gb, 3);
+ ss->prev_aspx_stop_freq = ss->aspx_stop_freq;
+ ss->aspx_stop_freq = get_bits(gb, 2);
+ ss->prev_aspx_master_freq_scale = ss->aspx_master_freq_scale;
+ ss->aspx_master_freq_scale = get_bits1(gb);
+ ss->aspx_interpolation = get_bits1(gb);
+ ss->aspx_preflat = get_bits1(gb);
+ ss->aspx_limiter = get_bits1(gb);
+ ss->aspx_noise_sbg = get_bits(gb, 2);
+ ss->aspx_num_env_bits_fixfix = get_bits1(gb);
+ ss->aspx_freq_res_mode = get_bits(gb, 2);
+
+ return 0;
+}
+
+static int get_transfer_length_from_idx(AC4DecodeContext *s, int idx)
+{
+ const uint16_t *transf_length_tab;
+
+ switch (s->frame_len_base) {
+ case 2048:
+ transf_length_tab = transf_length_48khz_2048;
+ break;
+ case 1920:
+ transf_length_tab = transf_length_48khz_1920;
+ break;
+ case 1536:
+ transf_length_tab = transf_length_48khz_1536;
+ break;
+ case 1024:
+ transf_length_tab = transf_length_48khz_1024;
+ break;
+ case 960:
+ transf_length_tab = transf_length_48khz_960;
+ break;
+ case 768:
+ transf_length_tab = transf_length_48khz_768;
+ break;
+ case 512:
+ transf_length_tab = transf_length_48khz_512;
+ break;
+ case 384:
+ transf_length_tab = transf_length_48khz_384;
+ break;
+ default:
+ av_assert0(0);
+ }
+
+ return transf_length_tab[idx];
+}
+
+static int asf_transform_info(AC4DecodeContext *s, Substream *ss,
+ SubstreamChannel *ssch)
+{
+ GetBitContext *gb = &s->gbc;
+
+ if (s->frame_len_base >= 1536) {
+ ssch->scp.long_frame = get_bits1(gb);
+ if (ssch->scp.long_frame == 0) {
+ ssch->scp.transf_length_idx[0] = get_bits(gb, 2);
+ ssch->scp.transf_length_idx[1] = get_bits(gb, 2);
+ ssch->scp.transf_length[0] = get_transfer_length_from_idx(s, ssch->scp.transf_length_idx[0]);
+ ssch->scp.transf_length[1] = get_transfer_length_from_idx(s, ssch->scp.transf_length_idx[1]);
+ } else {
+ ssch->scp.transf_length[0] = s->frame_len_base;
+ ssch->scp.transf_length[1] = 0;
+ }
+ } else {
+ ssch->scp.transf_length_idx[0] = get_bits(gb, 2);
+ ssch->scp.transf_length[0] = get_transfer_length_from_idx(s, ssch->scp.transf_length_idx[0]);
+ }
+
+ return 0;
+}
+
+static int get_grp_bits(AC4DecodeContext *s, SubstreamChannel *ssch)
+{
+ if (s->frame_len_base >= 1536 && ssch->scp.long_frame == 1)
+ return 0;
+
+ if (s->frame_len_base >= 1536 && ssch->scp.long_frame == 0)
+ return n_grp_bits_a[ssch->scp.transf_length_idx[0]][ssch->scp.transf_length_idx[1]];
+
+ if (s->frame_len_base < 1536 && s->frame_len_base > 512)
+ return n_grp_bits_b[ssch->scp.transf_length_idx[0]];
+
+ if (s->frame_len_base <= 512)
+ return n_grp_bits_c[ssch->scp.transf_length_idx[0]];
+
+ return 0;
+}
+
+static int get_msfb_bits(int transf_length)
+{
+ if (transf_length <= 2048 && transf_length >= 384)
+ return 6;
+
+ if (transf_length <= 256 && transf_length >= 192)
+ return 5;
+
+ return 4;
+}
+
+static int get_side_bits(int transf_length)
+{
+ if (transf_length <= 2048 && transf_length >= 480)
+ return 5;
+
+ if (transf_length <= 384 && transf_length >= 240)
+ return 4;
+
+ return 3;
+}
+
+static int get_max_sfb(AC4DecodeContext *s, SubstreamChannel *ssch,
+ int g)
+{
+ int idx = 0;
+
+ if (s->frame_len_base >= 1536 && (ssch->scp.long_frame == 0) &&
+ (ssch->scp.transf_length_idx[0] != ssch->scp.transf_length_idx[1])) {
+ int num_windows_0 = 1 << (3 - ssch->scp.transf_length_idx[0]);
+
+ if (g >= ssch->scp.window_to_group[num_windows_0])
+ idx = 1;
+ }
+
+ if ((ssch->scp.side_limited == 1) ||
+ (ssch->scp.dual_maxsfb == 1 && ssch->scp.side_channel == 1)) {
+ return ssch->scp.max_sfb_side[idx];
+ } else {
+ return ssch->scp.max_sfb[idx];
+ }
+}
+
+static int get_transf_length(AC4DecodeContext *s, SubstreamChannel *ssch, int g, int *idx)
+{
+ const uint16_t *transf_length_tab;
+
+ switch (s->frame_len_base) {
+ case 2048:
+ transf_length_tab = transf_length_48khz_2048;
+ break;
+ case 1920:
+ transf_length_tab = transf_length_48khz_1920;
+ break;
+ case 1536:
+ transf_length_tab = transf_length_48khz_1536;
+ break;
+ case 1024:
+ transf_length_tab = transf_length_48khz_1024;
+ break;
+ case 960:
+ transf_length_tab = transf_length_48khz_960;
+ break;
+ case 768:
+ transf_length_tab = transf_length_48khz_768;
+ break;
+ case 512:
+ transf_length_tab = transf_length_48khz_512;
+ break;
+ case 384:
+ transf_length_tab = transf_length_48khz_384;
+ break;
+ default:
+ av_assert0(0);
+ }
+
+ if (s->frame_len_base >= 1536) {
+ if (ssch->scp.long_frame == 0) {
+ int num_windows_0 = 1 << (3 - ssch->scp.transf_length_idx[0]);
+
+ if (g < ssch->scp.window_to_group[num_windows_0]) {
+ if (idx)
+ *idx = ssch->scp.transf_length_idx[0];
+ return transf_length_tab[ssch->scp.transf_length_idx[0]];
+ } else {
+ if (idx)
+ *idx = ssch->scp.transf_length_idx[1];
+ return transf_length_tab[ssch->scp.transf_length_idx[1]];
+ }
+ } else {
+ if (idx)
+ *idx = 4;
+ return s->frame_len_base; // long frame, the transform length equals to frame_length
+ }
+ } else {
+ if (idx)
+ *idx = ssch->scp.transf_length_idx[0];
+ return transf_length_tab[ssch->scp.transf_length_idx[0]];
+ }
+}
+
+static const int get_sfb_size(int transf_length)
+{
+ switch (transf_length) {
+ case 2048:
+ return FF_ARRAY_ELEMS(sfb_offset_48khz_2048);
+ break;
+ case 1920:
+ return FF_ARRAY_ELEMS(sfb_offset_48khz_1920);
+ break;
+ case 1536:
+ return FF_ARRAY_ELEMS(sfb_offset_48khz_1536);
+ break;
+ case 1024:
+ return FF_ARRAY_ELEMS(sfb_offset_48khz_1024);
+ break;
+ case 960:
+ return FF_ARRAY_ELEMS(sfb_offset_48khz_960);
+ break;
+ case 768:
+ return FF_ARRAY_ELEMS(sfb_offset_48khz_768);
+ break;
+ case 512:
+ return FF_ARRAY_ELEMS(sfb_offset_48khz_512);
+ break;
+ case 480:
+ return FF_ARRAY_ELEMS(sfb_offset_48khz_480);
+ break;
+ case 384:
+ return FF_ARRAY_ELEMS(sfb_offset_48khz_384);
+ break;
+ case 256:
+ return FF_ARRAY_ELEMS(sfb_offset_48khz_256);
+ break;
+ case 240:
+ return FF_ARRAY_ELEMS(sfb_offset_48khz_240);
+ break;
+ case 192:
+ return FF_ARRAY_ELEMS(sfb_offset_48khz_192);
+ break;
+ case 128:
+ return FF_ARRAY_ELEMS(sfb_offset_48khz_128);
+ break;
+ case 96:
+ return FF_ARRAY_ELEMS(sfb_offset_48khz_96);
+ break;
+ default:
+ av_assert0(0);
+ }
+ return 0;
+}
+
+static const uint16_t *get_sfb_offset(int transf_length)
+{
+ switch (transf_length) {
+ case 2048:
+ return sfb_offset_48khz_2048;
+ break;
+ case 1920:
+ return sfb_offset_48khz_1920;
+ break;
+ case 1536:
+ return sfb_offset_48khz_1536;
+ break;
+ case 1024:
+ return sfb_offset_48khz_1024;
+ break;
+ case 960:
+ return sfb_offset_48khz_960;
+ break;
+ case 768:
+ return sfb_offset_48khz_768;
+ break;
+ case 512:
+ return sfb_offset_48khz_512;
+ break;
+ case 480:
+ return sfb_offset_48khz_480;
+ break;
+ case 384:
+ return sfb_offset_48khz_384;
+ break;
+ case 256:
+ return sfb_offset_48khz_256;
+ break;
+ case 240:
+ return sfb_offset_48khz_240;
+ break;
+ case 192:
+ return sfb_offset_48khz_192;
+ break;
+ case 128:
+ return sfb_offset_48khz_128;
+ break;
+ case 96:
+ return sfb_offset_48khz_96;
+ break;
+ default:
+ av_assert0(0);
+ }
+
+ return 0;
+}
+
+static int num_sfb_96(int transf_length)
+{
+ if (transf_length >= 4096)
+ return 79;
+ else if (transf_length >= 3840)
+ return 76;
+ else if (transf_length >= 3072)
+ return 67;
+ else if (transf_length >= 2048)
+ return 57;
+ else if (transf_length >= 1920)
+ return 57;
+ else if (transf_length >= 1536)
+ return 49;
+ else if (transf_length >= 1024)
+ return 44;
+ else if (transf_length >= 920)
+ return 44;
+ else if (transf_length >= 768)
+ return 39;
+ else if (transf_length >= 512)
+ return 28;
+ else if (transf_length >= 480)
+ return 28;
+ else if (transf_length >= 384)
+ return 24;
+ else if (transf_length >= 256)
+ return 22;
+ else if (transf_length >= 240)
+ return 22;
+ else
+ return 18;
+}
+
+static int num_sfb_48(int transf_length)
+{
+ switch (transf_length) {
+ case 2048:
+ return 63; break;
+ case 1920:
+ return 61; break;
+ case 1536:
+ return 55; break;
+ case 1024:
+ case 960:
+ return 49; break;
+ case 768:
+ return 43; break;
+ case 512:
+ case 480:
+ return 36; break;
+ case 384:
+ return 33; break;
+ case 256:
+ case 240:
+ return 20; break;
+ case 192:
+ return 18; break;
+ case 128:
+ case 120:
+ return 14; break;
+ case 96:
+ return 12; break;
+ default:
+ av_assert0(0);
+ }
+
+ return 0;
+}
+
+static int asf_psy_elements(AC4DecodeContext *s, Substream *ss,
+ SubstreamChannel *ssch, int n_grp_bits)
+{
+ int group_offset, win_offset, win;
+
+ ssch->scp.num_windows = 1;
+ ssch->scp.num_window_groups = 1;
+ ssch->scp.window_to_group[0] = 0;
+
+ if (ssch->scp.long_frame == 0) {
+ ssch->scp.num_windows = n_grp_bits + 1;
+ if (ssch->scp.different_framing) {
+ int num_windows_0 = 1 << (3 - ssch->scp.transf_length_idx[0]);
+
+ for (int i = n_grp_bits; i >= num_windows_0; i--) {
+ ssch->scp.scale_factor_grouping[i] = ssch->scp.scale_factor_grouping[i - 1];
+ }
+
+ ssch->scp.scale_factor_grouping[num_windows_0 - 1] = 0;
+ ssch->scp.num_windows++;
+ }
+
+ for (int i = 0; i < ssch->scp.num_windows - 1; i++) {
+ if (ssch->scp.scale_factor_grouping[i] == 0) {
+ ssch->scp.num_window_groups++;
+ }
+
+ ssch->scp.window_to_group[i + 1] = ssch->scp.num_window_groups - 1;
+ }
+ }
+
+ group_offset = 0;
+ win_offset = 0;
+ win = 0;
+ memset(ssch->offset2sfb, 0, sizeof(ssch->offset2sfb));
+ memset(ssch->offset2g, 0, sizeof(ssch->offset2g));
+ for (int g = 0; g < ssch->scp.num_window_groups; g++) {
+ int transf_length_g = get_transf_length(s, ssch, g, NULL);
+ const uint16_t *sfb_offset = get_sfb_offset(transf_length_g);
+ const int sfb_max_size = get_sfb_size(transf_length_g);
+ int max_sfb;
+
+ ssch->scp.num_win_in_group[g] = 0;
+ for (int w = 0; w < ssch->scp.num_windows; w++) {
+ if (ssch->scp.window_to_group[w] == g)
+ ssch->scp.num_win_in_group[g]++;
+ }
+
+ max_sfb = get_max_sfb(s, ssch, g);
+ if (max_sfb > sfb_max_size) {
+ av_log(s->avctx, AV_LOG_ERROR, "max_sfb=%d > sfb_max_size=%d\n", max_sfb, sfb_max_size);
+ return AVERROR_INVALIDDATA;
+ }
+ for (int sfb = 0; sfb < max_sfb; sfb++)
+ ssch->sect_sfb_offset[g][sfb] = group_offset + sfb_offset[sfb] * ssch->scp.num_win_in_group[g];
+ group_offset += sfb_offset[max_sfb] * ssch->scp.num_win_in_group[g];
+ ssch->sect_sfb_offset[g][max_sfb] = group_offset;
+ for (int sfb = 0; sfb < max_sfb; sfb++) {
+ for (int j = ssch->sect_sfb_offset[g][sfb]; j < ssch->sect_sfb_offset[g][sfb+1]; j++) {
+ ssch->offset2sfb[j] = sfb;
+ ssch->offset2g[j] = g;
+ }
+ }
+
+ for (int w = 0; w < ssch->scp.num_win_in_group[g]; w++) {
+ ssch->win_offset[win + w] = win_offset;
+ win_offset += transf_length_g;
+ }
+ win += ssch->scp.num_win_in_group[g];
+ }
+
+ av_log(s->avctx, AV_LOG_DEBUG, "long_frame: %d\n", ssch->scp.long_frame);
+ av_log(s->avctx, AV_LOG_DEBUG, "different_framing: %d\n", ssch->scp.different_framing);
+ av_log(s->avctx, AV_LOG_DEBUG, "num_windows: %d\n", ssch->scp.num_windows);
+ av_log(s->avctx, AV_LOG_DEBUG, "num_window_groups: %d\n", ssch->scp.num_window_groups);
+ av_log(s->avctx, AV_LOG_DEBUG, "transf_lengths:");
+ for (int g = 0; g < ssch->scp.num_window_groups; g++) {
+ av_log(s->avctx, AV_LOG_DEBUG, " %d", get_transf_length(s, ssch, g, NULL));
+ }
+ av_log(s->avctx, AV_LOG_DEBUG, "\n");
+ av_log(s->avctx, AV_LOG_DEBUG, "num_win_in_group:");
+ for (int g = 0; g < ssch->scp.num_window_groups; g++) {
+ av_log(s->avctx, AV_LOG_DEBUG, " %d", ssch->scp.num_win_in_group[g]);
+ }
+ av_log(s->avctx, AV_LOG_DEBUG, "\n");
+
+ return 0;
+}
+
+static int asf_psy_info(AC4DecodeContext *s, Substream *ss,
+ SubstreamChannel *ssch,
+ int dual_maxsfb, int side_limited)
+{
+ GetBitContext *gb = &s->gbc;
+ int n_side_bits = get_side_bits(ssch->scp.transf_length[0]);
+ int n_msfb_bits = get_msfb_bits(ssch->scp.transf_length[0]);
+ int n_grp_bits = get_grp_bits(s, ssch);
+
+ ssch->scp.different_framing = 0;
+ if ((s->frame_len_base >= 1536) && (ssch->scp.long_frame == 0) &&
+ (ssch->scp.transf_length_idx[0] != ssch->scp.transf_length_idx[1])) {
+ ssch->scp.different_framing = 1;
+ }
+
+ if (side_limited) {
+ ssch->scp.max_sfb_side[0] = get_bits(gb, n_side_bits);
+ } else {
+ ssch->scp.max_sfb[0] = get_bits(gb, n_msfb_bits);
+ if (dual_maxsfb)
+ ssch->scp.max_sfb_side[0] = get_bits(gb, n_msfb_bits);
+ }
+
+ if (ssch->scp.different_framing) {
+ n_side_bits = get_side_bits(ssch->scp.transf_length[1]);
+ n_msfb_bits = get_msfb_bits(ssch->scp.transf_length[1]);
+
+ if (side_limited) {
+ ssch->scp.max_sfb_side[1] = get_bits(gb, n_side_bits);
+ } else {
+ ssch->scp.max_sfb[1] = get_bits(gb, n_msfb_bits);
+ if (dual_maxsfb)
+ ssch->scp.max_sfb_side[1] = get_bits(gb, n_msfb_bits);
+ }
+ }
+
+ memset(ssch->scp.scale_factor_grouping, 0, sizeof(ssch->scp.scale_factor_grouping));
+ for (int i = 0; i < n_grp_bits; i++)
+ ssch->scp.scale_factor_grouping[i] = get_bits1(gb);
+
+ return asf_psy_elements(s, ss, ssch, n_grp_bits);
+}
+
+static int sf_info(AC4DecodeContext *s, Substream *ss,
+ SubstreamChannel *ssch,
+ int spec_frontend, int dual_maxsfb,
+ int side_limited)
+{
+ int ret = 0;
+
+ ssch->scp.dual_maxsfb = dual_maxsfb;
+ ssch->scp.side_limited = side_limited;
+
+ if (spec_frontend == SF_ASF) {
+ asf_transform_info(s, ss, ssch);
+ ret = asf_psy_info(s, ss, ssch, dual_maxsfb, side_limited);
+ }
+
+ return ret;
+}
+
+static int sap_data(AC4DecodeContext *s, Substream *ss, SubstreamChannel *ssch)
+{
+ GetBitContext *gb = &s->gbc;
+
+ if (!get_bits1(gb)) {
+ for (int g = 0; g < ssch->scp.num_window_groups; g++) {
+ int max_sfb_g = get_max_sfb(s, ssch, g);
+
+ for (int sfb = 0; sfb < max_sfb_g; sfb += 2) {
+ ssch->sap_coeff_used[g][sfb] = get_bits1(gb);
+ if (sfb + 1 < max_sfb_g)
+ ssch->sap_coeff_used[g][sfb + 1] = ssch->sap_coeff_used[g][sfb];
+ }
+ }
+ } else {
+ for (int g = 0; g < ssch->scp.num_window_groups; g++) {
+ int max_sfb_g = get_max_sfb(s, ssch, g);
+
+ for (int sfb = 0; sfb < max_sfb_g; sfb++)
+ ssch->sap_coeff_used[g][sfb] = 1;
+ }
+ }
+
+ ssch->delta_code_time = 0;
+ if (ssch->scp.num_window_groups != 1)
+ ssch->delta_code_time = get_bits1(gb);
+
+ for (int g = 0; g < ssch->scp.num_window_groups; g++) {
+ int max_sfb_g = get_max_sfb(s, ssch, g);
+
+ for (int sfb = 0; sfb < max_sfb_g; sfb += 2) {
+ if (ssch->sap_coeff_used[g][sfb]) {
+ ssch->dpcm_alpha_q[g][sfb] = get_vlc2(gb, scale_factors_vlc.table, scale_factors_vlc.bits, 3);
+ if (ssch->dpcm_alpha_q[g][sfb] < 0)
+ return AVERROR_INVALIDDATA;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int ssf_data(AC4DecodeContext *s, Substream *ss,
+ SubstreamChannel *ssch, int iframe)
+{
+ av_assert0(0);
+
+ return 0;
+}
+
+static int asf_section_data(AC4DecodeContext *s, Substream *ss, SubstreamChannel *ssch)
+{
+ GetBitContext *gb = &s->gbc;
+
+ memset(&ssch->sect_cb, 0, sizeof(ssch->sect_cb));
+ memset(&ssch->sfb_cb, 0, sizeof(ssch->sfb_cb));
+
+ for (int g = 0; g < ssch->scp.num_window_groups; g++) {
+ int transf_length_g = get_transf_length(s, ssch, g, NULL);
+ int sect_esc_val;
+ int n_sect_bits;
+ int k, i, max_sfb;
+
+ if (transf_length_g <= 512) {
+ sect_esc_val = (1 << 3) - 1;
+ n_sect_bits = 3;
+ } else {
+ sect_esc_val = (1 << 5) - 1;
+ n_sect_bits = 5;
+ }
+ k = 0;
+ i = 0;
+ ssch->num_sec_lsf[g] = 0;
+ max_sfb = get_max_sfb(s, ssch, g);
+ while (k < max_sfb) {
+ int sect_len_incr;
+ int sect_len;
+
+ ssch->sect_cb[g][i] = get_bits(gb, 4);
+ if (ssch->sect_cb[g][i] > 11) {
+ av_log(s->avctx, AV_LOG_ERROR, "sect_cb[%d][%d] > 11\n", g, i);
+ return AVERROR_INVALIDDATA;
+ }
+ sect_len = 1;
+ sect_len_incr = get_bits(gb, n_sect_bits);
+ while (sect_len_incr == sect_esc_val) {
+ sect_len += sect_esc_val;
+ sect_len_incr = get_bits(gb, n_sect_bits);
+ }
+
+ sect_len += sect_len_incr;
+ ssch->sect_start[g][i] = k;
+ ssch->sect_end[g][i] = k + sect_len;
+
+ if (ssch->sect_start[g][i] < num_sfb_48(transf_length_g) &&
+ ssch->sect_end[g][i] >= num_sfb_48(transf_length_g)) {
+ ssch->num_sec_lsf[g] = i + 1;
+ if (ssch->sect_end[g][i] > num_sfb_48(transf_length_g)) {
+ ssch->sect_end[g][i] = num_sfb_48(transf_length_g);
+ i++;
+ ssch->sect_start[g][i] = num_sfb_48(transf_length_g);
+ ssch->sect_end[g][i] = k + sect_len;
+ ssch->sect_cb[g][i] = ssch->sect_cb[g][i-1];
+ }
+ }
+
+ for (int sfb = k; sfb < k + sect_len; sfb++)
+ ssch->sfb_cb[g][sfb] = ssch->sect_cb[g][i];
+ k += sect_len;
+ i++;
+ }
+
+ ssch->num_sec[g] = i;
+ if (ssch->num_sec_lsf[g] == 0)
+ ssch->num_sec_lsf[g] = ssch->num_sec[g];
+ }
+
+ return 0;
+}
+
+static int ext_decode(AC4DecodeContext *s)
+{
+ GetBitContext *gb = &s->gbc;
+ int b, ext_val, N_ext = 0;
+
+ b = get_bits1(gb);
+ while (b) {
+ N_ext++;
+ b = get_bits1(gb);
+ }
+
+ ext_val = get_bits(gb, N_ext + 4);
+
+ return (1 << (N_ext + 4)) + ext_val;
+}
+
+static int asf_spectral_data(AC4DecodeContext *s, Substream *ss, SubstreamChannel *ssch)
+{
+ GetBitContext *gb = &s->gbc;
+
+ memset(&ssch->max_quant_idx, 0, sizeof(ssch->max_quant_idx));
+ memset(&ssch->quant_spec, 0, sizeof(ssch->quant_spec));
+
+ for (int g = 0; g < ssch->scp.num_window_groups; g++) {
+ for (int i = 0; i < ssch->num_sec_lsf[g]; i++) {
+ int sect_start_line, sect_end_line, cb;
+
+ if (ssch->sect_cb[g][i] == 0 || ssch->sect_cb[g][i] > 11)
+ continue;
+
+ sect_start_line = ssch->sect_sfb_offset[g][ssch->sect_start[g][i]];
+ sect_end_line = ssch->sect_sfb_offset[g][ssch->sect_end[g][i]];
+ cb = ssch->sect_cb[g][i] - 1;
+
+ for (int k = sect_start_line; k < sect_end_line;) {
+ int cb_off = asf_codebook_off[cb];
+ int cb_mod = asf_codebook_mod[cb];
+ int x;
+
+ if (asf_codebook_dim[cb] == 4) {
+ int cb_idx = get_vlc2(gb, asf_codebook_vlc[cb].table, asf_codebook_vlc[cb].bits, 3);
+ int cb_mod2 = 9;
+ int cb_mod3 = 27;
+
+ if (cb_idx < 0)
+ return AVERROR_INVALIDDATA;
+
+ ssch->quant_spec[k] = (cb_idx / cb_mod3) - cb_off;
+ cb_idx -= (ssch->quant_spec[k] + cb_off) * cb_mod3;
+ ssch->quant_spec[k+1] = (cb_idx / cb_mod2) - cb_off;
+ cb_idx -= (ssch->quant_spec[k+1] + cb_off) * cb_mod2;
+ ssch->quant_spec[k+2] = (cb_idx / cb_mod) - cb_off;
+ cb_idx -= (ssch->quant_spec[k+2] + cb_off) * cb_mod;
+ ssch->quant_spec[k+3] = cb_idx - cb_off;
+
+ if (asf_codebook_unsigned[cb]) {
+ if (ssch->quant_spec[k] && get_bits1(gb))
+ ssch->quant_spec[k] = -ssch->quant_spec[k];
+ if (ssch->quant_spec[k+1] && get_bits1(gb))
+ ssch->quant_spec[k+1] = -ssch->quant_spec[k+1];
+ if (ssch->quant_spec[k+2] && get_bits1(gb))
+ ssch->quant_spec[k+2] = -ssch->quant_spec[k+2];
+ if (ssch->quant_spec[k+3] && get_bits1(gb))
+ ssch->quant_spec[k+3] = -ssch->quant_spec[k+3];
+ }
+ x = ssch->offset2sfb[k];
+ ssch->max_quant_idx[g][x] = FFMAX(ssch->max_quant_idx[g][x], FFABS(ssch->quant_spec[k]));
+ x = ssch->offset2sfb[k+1];
+ ssch->max_quant_idx[g][x] = FFMAX(ssch->max_quant_idx[g][x], FFABS(ssch->quant_spec[k+1]));
+ x = ssch->offset2sfb[k+2];
+ ssch->max_quant_idx[g][x] = FFMAX(ssch->max_quant_idx[g][x], FFABS(ssch->quant_spec[k+2]));
+ x = ssch->offset2sfb[k+3];
+ ssch->max_quant_idx[g][x] = FFMAX(ssch->max_quant_idx[g][x], FFABS(ssch->quant_spec[k+3]));
+ k += 4;
+ } else { /* (asf_codebook_dim[ssch->sect_cb[g][i]] == 2) */
+ int cb_idx = get_vlc2(gb, asf_codebook_vlc[cb].table, asf_codebook_vlc[cb].bits, 3);
+ int sign0 = 0, sign1 = 0;
+
+ if (cb_idx < 0)
+ return AVERROR_INVALIDDATA;
+
+ ssch->quant_spec[k] = (cb_idx / cb_mod) - cb_off;
+ cb_idx -= (ssch->quant_spec[k] + cb_off) * cb_mod;
+ ssch->quant_spec[k+1] = cb_idx - cb_off;
+
+ if (asf_codebook_unsigned[cb]) {
+ if (ssch->quant_spec[k] && get_bits1(gb))
+ sign0 = 1;
+ if (ssch->quant_spec[k+1] && get_bits1(gb))
+ sign1 = 1;
+ }
+ if (ssch->sect_cb[g][i] == 11) {
+ if (ssch->quant_spec[k] == 16)
+ ssch->quant_spec[k] = ext_decode(s);
+ if (ssch->quant_spec[k+1] == 16)
+ ssch->quant_spec[k+1] = ext_decode(s);
+ }
+
+ if (sign0)
+ ssch->quant_spec[k] = -ssch->quant_spec[k];
+ if (sign1)
+ ssch->quant_spec[k+1] = -ssch->quant_spec[k+1];
+
+ x = ssch->offset2sfb[k];
+ ssch->max_quant_idx[g][x] = FFMAX(ssch->max_quant_idx[g][x], FFABS(ssch->quant_spec[k]));
+ x = ssch->offset2sfb[k+1];
+ ssch->max_quant_idx[g][x] = FFMAX(ssch->max_quant_idx[g][x], FFABS(ssch->quant_spec[k+1]));
+ k += 2;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int asf_scalefac_data(AC4DecodeContext *s, Substream *ss, SubstreamChannel *ssch)
+{
+ GetBitContext *gb = &s->gbc;
+ int first_scf_found = 0;
+ int scale_factor;
+
+ scale_factor = get_bits(gb, 8);
+ memset(ssch->sf_gain, 0, sizeof(ssch->sf_gain));
+
+ for (int g = 0; g < ssch->scp.num_window_groups; g++) {
+ int max_sfb = FFMIN(get_max_sfb(s, ssch, g), num_sfb_48(get_transf_length(s, ssch, g, NULL)));
+
+ for (int sfb = 0; sfb < max_sfb; sfb++) {
+ if ((ssch->sfb_cb[g][sfb]) != 0 && (ssch->max_quant_idx[g][sfb] > 0)) {
+ if (first_scf_found == 1) {
+ ssch->dpcm_sf[g][sfb] = get_vlc2(gb, scale_factors_vlc.table, scale_factors_vlc.bits, 3);
+ if (ssch->dpcm_sf[g][sfb] < 0)
+ return AVERROR_INVALIDDATA;
+ scale_factor += ssch->dpcm_sf[g][sfb] - 60;
+ } else {
+ first_scf_found = 1;
+ }
+
+ ssch->sf_gain[g][sfb] = powf(2.f, 0.25f * (scale_factor - 100));
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int asf_snf_data(AC4DecodeContext *s, Substream *ss, SubstreamChannel *ssch)
+{
+ GetBitContext *gb = &s->gbc;
+
+ ssch->snf_data_exists = get_bits1(gb);
+ if (ssch->snf_data_exists) {
+ for (int g = 0; g < ssch->scp.num_window_groups; g++) {
+ int transf_length_g = get_transf_length(s, ssch, g, NULL);
+ int max_sfb = FFMIN(get_max_sfb(s, ssch, g), num_sfb_48(transf_length_g));
+
+ for (int sfb = 0; sfb < max_sfb; sfb++) {
+ if ((ssch->sfb_cb[g][sfb] == 0) || (ssch->max_quant_idx[g][sfb] == 0)) {
+ ssch->dpcm_snf[g][sfb] = get_vlc2(gb, snf_vlc.table, snf_vlc.bits, 3);
+ if (ssch->dpcm_snf[g][sfb] < 0)
+ return AVERROR_INVALIDDATA;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int sf_data(AC4DecodeContext *s, Substream *ss, SubstreamChannel *ssch,
+ int iframe, int spec_frontend)
+{
+ int ret;
+
+ if (spec_frontend == SF_ASF) {
+ ret = asf_section_data(s, ss, ssch);
+ if (ret < 0)
+ return ret;
+ ret = asf_spectral_data(s, ss, ssch);
+ if (ret < 0)
+ return ret;
+ ret = asf_scalefac_data(s, ss, ssch);
+ if (ret < 0)
+ return ret;
+ ret = asf_snf_data(s, ss, ssch);
+ if (ret < 0)
+ return ret;
+ } else {
+ ssf_data(s, ss, ssch, iframe);
+ }
+
+ return 0;
+}
+
+static int chparam_info(AC4DecodeContext *s, Substream *ss, SubstreamChannel *ssch)
+{
+ GetBitContext *gb = &s->gbc;
+ int ret;
+
+ ssch->sap_mode = get_bits(gb, 2);
+ av_log(s->avctx, AV_LOG_DEBUG, "sap_mode: %d\n", ssch->sap_mode);
+
+ if (ssch->sap_mode == 1) {
+ for (int g = 0; g < ssch->scp.num_window_groups; g++) {
+ int max_sfb_g = get_max_sfb(s, ssch, g);
+
+ for (int sfb = 0; sfb < max_sfb_g; sfb++) {
+ ssch->ms_used[g][sfb] = get_bits1(gb);
+ }
+ }
+ }
+
+ if (ssch->sap_mode == 3) {
+ ret = sap_data(s, ss, ssch);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int stereo_data(AC4DecodeContext *s, Substream *ss, int iframe)
+{
+ GetBitContext *gb = &s->gbc;
+ int ret;
+
+ ss->mdct_stereo_proc[0] = get_bits1(gb);
+ if (ss->mdct_stereo_proc[0]) {
+ ss->spec_frontend_l = SF_ASF;
+ ss->spec_frontend_r = SF_ASF;
+ ret = sf_info(s, ss, &ss->ssch[0], SF_ASF, 0, 0);
+ if (ret < 0)
+ return ret;
+
+ memcpy(&ss->ssch[1].scp, &ss->ssch[0].scp, sizeof(ss->ssch[0].scp));
+ memcpy(&ss->ssch[1].sect_sfb_offset, &ss->ssch[0].sect_sfb_offset, sizeof(ss->ssch[0].sect_sfb_offset));
+ memcpy(&ss->ssch[1].offset2sfb, &ss->ssch[0].offset2sfb, sizeof(ss->ssch[0].offset2sfb));
+ memcpy(&ss->ssch[1].offset2g, &ss->ssch[0].offset2g, sizeof(ss->ssch[0].offset2g));
+ memcpy(&ss->ssch[1].win_offset, &ss->ssch[0].win_offset, sizeof(ss->ssch[0].win_offset));
+
+ ret = chparam_info(s, ss, &ss->ssch[0]);
+ if (ret < 0)
+ return ret;
+ } else {
+ ss->spec_frontend_l = get_bits1(gb);
+ sf_info(s, ss, &ss->ssch[0], ss->spec_frontend_l, 0, 0);
+ ss->spec_frontend_r = get_bits1(gb);
+ sf_info(s, ss, &ss->ssch[1], ss->spec_frontend_r, 0, 0);
+ }
+
+ ret = sf_data(s, ss, &ss->ssch[0], iframe, ss->spec_frontend_l);
+ if (ret < 0)
+ return ret;
+ ret = sf_data(s, ss, &ss->ssch[1], iframe, ss->spec_frontend_r);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int companding_control(AC4DecodeContext *s, Substream *ss, int num_chan)
+{
+ GetBitContext *gb = &s->gbc;
+ int sync_flag = 0;
+ int need_avg = 0;
+ int nc;
+
+ if (num_chan > 1)
+ sync_flag = get_bits1(gb);
+
+ nc = sync_flag ? 1 : num_chan;
+
+ for (int i = 0; i < nc; i++) {
+ ss->compand_on[i] = get_bits1(gb);
+ if (!ss->compand_on[i])
+ need_avg = 1;
+ }
+
+ if (need_avg == 1)
+ ss->compand_avg = get_bits1(gb);
+
+ return 0;
+}
+
+static int noise_mid_border(int aspx_tsg_ptr, int aspx_int_class, int num_atsg_sig)
+{
+ if (aspx_tsg_ptr == -1) {
+ if (aspx_int_class == VARFIX)
+ return 1;
+ else
+ return num_atsg_sig - 1;
+ } else if (aspx_tsg_ptr >= 0) {
+ if (aspx_int_class == VARFIX)
+ return num_atsg_sig - 1;
+ else
+ return FFMAX(1, FFMIN(num_atsg_sig - 1, aspx_tsg_ptr));
+ } else {
+ av_assert0(0);
+ }
+
+ return 0;
+}
+
+static int freq_res(int *atsg_sig, int atsg, int aspx_tsg_ptr,
+ int num_aspx_timeslots, int aspx_freq_res_mode,
+ int *aspx_freq_res)
+{
+ int freq_res;
+
+ switch (aspx_freq_res_mode) {
+ case 0:
+ freq_res = aspx_freq_res[atsg];
+ break;
+ case 1:
+ freq_res = 0;
+ break;
+ case 2:
+ if ((atsg < aspx_tsg_ptr && num_aspx_timeslots > 8) ||
+ (atsg_sig[atsg+1]-atsg_sig[atsg]) > (num_aspx_timeslots/6.0+3.25))
+ freq_res = 1;
+ else
+ freq_res = 0;
+ break;
+ case 3:
+ freq_res = 1;
+ break;
+ default:
+ av_assert0(0);
+ }
+
+ return freq_res;
+}
+
+static void get_tab_border(int *atsg_sig, int num_aspx_timeslots, int num_atsg)
+{
+ switch (num_aspx_timeslots) {
+ case 6:
+ memcpy(atsg_sig, tab_border[0][num_atsg >> 1], sizeof(tab_border[0][0]));
+ break;
+ case 8:
+ memcpy(atsg_sig, tab_border[1][num_atsg >> 1], sizeof(tab_border[0][0]));
+ break;
+ case 12:
+ memcpy(atsg_sig, tab_border[2][num_atsg >> 1], sizeof(tab_border[0][0]));
+ break;
+ case 15:
+ memcpy(atsg_sig, tab_border[3][num_atsg >> 1], sizeof(tab_border[0][0]));
+ break;
+ case 16:
+ memcpy(atsg_sig, tab_border[4][num_atsg >> 1], sizeof(tab_border[0][0]));
+ break;
+ default:
+ av_assert0(0);
+ }
+}
+
+static int aspx_atsg(AC4DecodeContext *s, Substream *ss, SubstreamChannel *ssch, int iframe)
+{
+ int num_atsg_sig = ssch->aspx_num_env;
+ int num_atsg_noise = ssch->aspx_num_noise;
+
+ if (ssch->aspx_int_class == FIXFIX) {
+ get_tab_border(ssch->atsg_sig, s->num_aspx_timeslots, num_atsg_sig);
+ get_tab_border(ssch->atsg_noise, s->num_aspx_timeslots, num_atsg_noise);
+ ssch->atsg_freqres[0] = freq_res(ssch->atsg_sig, 0, 0, s->num_aspx_timeslots,
+ ss->aspx_freq_res_mode, ssch->aspx_freq_res);
+ for (int atsg = 1; atsg < num_atsg_sig; atsg++)
+ ssch->atsg_freqres[atsg] = ssch->atsg_freqres[0];
+ } else {
+ switch (ssch->aspx_int_class) {
+ case FIXVAR:
+ ssch->atsg_sig[0] = 0;
+ ssch->atsg_sig[num_atsg_sig] = ssch->aspx_var_bord_right + s->num_aspx_timeslots;
+ for (int tsg = 0; tsg < ssch->aspx_num_rel_right; tsg++)
+ ssch->atsg_sig[num_atsg_sig-tsg-1] = ssch->atsg_sig[num_atsg_sig-tsg] - ssch->aspx_rel_bord_right[tsg];
+ break;
+ case VARFIX:
+ if (iframe)
+ ssch->atsg_sig[0] = ssch->aspx_var_bord_left;
+ else
+ ssch->atsg_sig[0] = ssch->previous_stop_pos - s->num_aspx_timeslots;
+ ssch->atsg_sig[num_atsg_sig] = s->num_aspx_timeslots;
+ for (int tsg = 0; tsg < ssch->aspx_num_rel_left; tsg++)
+ ssch->atsg_sig[tsg+1] = ssch->atsg_sig[tsg] + ssch->aspx_rel_bord_left[tsg];
+ break;
+ case VARVAR:
+ if (iframe)
+ ssch->atsg_sig[0] = ssch->aspx_var_bord_left;
+ else
+ ssch->atsg_sig[0] = ssch->previous_stop_pos - s->num_aspx_timeslots;
+ ssch->atsg_sig[num_atsg_sig] = ssch->aspx_var_bord_right + s->num_aspx_timeslots;
+ for (int tsg = 0; tsg < ssch->aspx_num_rel_left; tsg++)
+ ssch->atsg_sig[tsg+1] = ssch->atsg_sig[tsg] + ssch->aspx_rel_bord_left[tsg];
+ for (int tsg = 0; tsg < ssch->aspx_num_rel_right; tsg++)
+ ssch->atsg_sig[num_atsg_sig-tsg-1] = ssch->atsg_sig[num_atsg_sig-tsg] - ssch->aspx_rel_bord_right[tsg];
+ break;
+ }
+
+ ssch->atsg_noise[0] = ssch->atsg_sig[0];
+ ssch->atsg_noise[num_atsg_noise] = ssch->atsg_sig[num_atsg_sig];
+ if (num_atsg_noise > 1)
+ ssch->atsg_noise[1] = ssch->atsg_sig[noise_mid_border(ssch->aspx_tsg_ptr,
+ ssch->aspx_int_class,
+ num_atsg_sig)];
+ for (int atsg = 0; atsg < num_atsg_sig; atsg++)
+ ssch->atsg_freqres[atsg] = freq_res(ssch->atsg_sig, atsg, ssch->aspx_tsg_ptr,
+ s->num_aspx_timeslots, ss->aspx_freq_res_mode,
+ ssch->aspx_freq_res);
+ }
+
+ ssch->previous_stop_pos = ssch->atsg_sig[num_atsg_sig];
+
+ for (int atsg = 0; atsg < num_atsg_sig; atsg++) {
+ if (ssch->atsg_freqres[atsg]) {
+ ssch->num_sbg_sig[atsg] = ssch->num_sbg_sig_highres;
+ memcpy(ssch->sbg_sig[atsg], ssch->sbg_sig_highres, 24 * 4);
+ } else {
+ ssch->num_sbg_sig[atsg] = ssch->num_sbg_sig_lowres;
+ memcpy(ssch->sbg_sig[atsg], ssch->sbg_sig_lowres, 24 * 4);
+ }
+ }
+
+ return 0;
+}
+
+static int aspx_framing(AC4DecodeContext *s, Substream *ss, SubstreamChannel *ssch, int iframe)
+{
+ GetBitContext *gb = &s->gbc;
+
+ ssch->aspx_num_rel_left = 0;
+ ssch->aspx_num_rel_right = 0;
+
+ ssch->aspx_int_class = get_vlc2(gb, aspx_int_class_vlc.table, aspx_int_class_vlc.bits, 1);
+ if (ssch->aspx_int_class < 0)
+ return AVERROR_INVALIDDATA;
+
+ ssch->aspx_num_env_prev = ssch->aspx_num_env;
+
+ switch (ssch->aspx_int_class) {
+ case FIXFIX:
+ ssch->aspx_num_env = 1 << get_bits(gb, 1 + ss->aspx_num_env_bits_fixfix);
+ if (ss->aspx_freq_res_mode == 0)
+ ssch->aspx_freq_res[0] = get_bits1(gb);
+ break;
+ case FIXVAR:
+ ssch->aspx_var_bord_right = get_bits(gb, 2);
+ ssch->aspx_num_rel_right = get_bits(gb, 1 + (s->num_aspx_timeslots > 8));
+ for (int i = 0; i < ssch->aspx_num_rel_right; i++)
+ ssch->aspx_rel_bord_right[i] = 2 * get_bits(gb, 1 + (s->num_aspx_timeslots > 8)) + 2;
+ break;
+ case VARFIX:
+ if (iframe)
+ ssch->aspx_var_bord_left = get_bits(gb, 2);
+ ssch->aspx_num_rel_left = get_bits(gb, 1 + (s->num_aspx_timeslots > 8));
+ for (int i = 0; i < ssch->aspx_num_rel_left; i++)
+ ssch->aspx_rel_bord_left[i] = 2 * get_bits(gb, 1 + (s->num_aspx_timeslots > 8)) + 2;
+ break;
+ case VARVAR:
+ if (iframe)
+ ssch->aspx_var_bord_left = get_bits(gb, 2);
+ ssch->aspx_num_rel_left = get_bits(gb, 1 + (s->num_aspx_timeslots > 8));
+ for (int i = 0; i < ssch->aspx_num_rel_left; i++)
+ ssch->aspx_rel_bord_left[i] = 2 * get_bits(gb, 1 + (s->num_aspx_timeslots > 8)) + 2;
+ ssch->aspx_var_bord_right = get_bits(gb, 2);
+ ssch->aspx_num_rel_right = get_bits(gb, 1 + (s->num_aspx_timeslots > 8));
+ for (int i = 0; i < ssch->aspx_num_rel_right; i++)
+ ssch->aspx_rel_bord_right[i] = 2 * get_bits(gb, 1 + (s->num_aspx_timeslots > 8)) + 2;
+ break;
+ }
+
+ if (ssch->aspx_int_class != FIXFIX) {
+ int ptr_bits;
+
+ ssch->aspx_num_env = ssch->aspx_num_rel_left + ssch->aspx_num_rel_right + 1;
+ ptr_bits = ceilf(logf(ssch->aspx_num_env + 2) / logf(2));
+ ssch->aspx_tsg_ptr_prev = ssch->aspx_tsg_ptr;
+ ssch->aspx_tsg_ptr = (int)get_bits(gb, ptr_bits) - 1;
+ if (ss->aspx_freq_res_mode == 0)
+ for (int env = 0; env < ssch->aspx_num_env; env++)
+ ssch->aspx_freq_res[env] = get_bits1(gb);
+ }
+
+ ssch->aspx_num_noise_prev = ssch->aspx_num_noise;
+
+ if (ssch->aspx_num_env > 1)
+ ssch->aspx_num_noise = 2;
+ else
+ ssch->aspx_num_noise = 1;
+
+ if (!ssch->aspx_num_env_prev)
+ ssch->aspx_num_env_prev = ssch->aspx_num_env;
+ if (!ssch->aspx_num_noise_prev)
+ ssch->aspx_num_noise_prev = ssch->aspx_num_noise;
+
+ return aspx_atsg(s, ss, ssch, iframe);
+}
+
+static void aspx_delta_dir(AC4DecodeContext *s, SubstreamChannel *ssch)
+{
+ GetBitContext *gb = &s->gbc;
+
+ for (int env = 0; env < ssch->aspx_num_env; env++)
+ ssch->aspx_sig_delta_dir[env] = get_bits1(gb);
+ for (int env = 0; env < ssch->aspx_num_noise; env++)
+ ssch->aspx_noise_delta_dir[env] = get_bits1(gb);
+}
+
+static int aspx_hfgen_iwc_2ch(AC4DecodeContext *s, Substream *ss,
+ SubstreamChannel *ssch0,
+ SubstreamChannel *ssch1,
+ int aspx_balance)
+{
+ GetBitContext *gb = &s->gbc;
+ int aspx_tic_left = 0, aspx_tic_right = 0;
+
+ memcpy(ssch0->aspx_tna_mode_prev, ssch0->aspx_tna_mode, sizeof(ssch0->aspx_tna_mode));
+ memcpy(ssch1->aspx_tna_mode_prev, ssch1->aspx_tna_mode, sizeof(ssch1->aspx_tna_mode));
+
+ for (int n = 0; n < ssch0->num_sbg_noise; n++)
+ ssch0->aspx_tna_mode[n] = get_bits(gb, 2);
+ if (aspx_balance == 0) {
+ for (int n = 0; n < ssch0->num_sbg_noise; n++)
+ ssch1->aspx_tna_mode[n] = get_bits(gb, 2);
+ } else {
+ for (int n = 0; n < ssch0->num_sbg_noise; n++)
+ ssch1->aspx_tna_mode[n] = ssch0->aspx_tna_mode[n];
+ }
+ if (get_bits1(gb)) {
+ for (int n = 0; n < ssch0->num_sbg_sig_highres; n++)
+ ssch0->aspx_add_harmonic[n] = get_bits1(gb);
+ }
+ if (get_bits1(gb)) {
+ for (int n = 0; n < ssch0->num_sbg_sig_highres; n++)
+ ssch1->aspx_add_harmonic[n] = get_bits1(gb);
+ }
+
+ for (int n = 0; n < ssch0->num_sbg_sig_highres; n++)
+ ssch0->aspx_fic_used_in_sfb[n] = ssch1->aspx_fic_used_in_sfb[n] = 0;
+
+ if (get_bits1(gb)) {
+ if (get_bits1(gb)) {
+ for (int n = 0; n < ssch0->num_sbg_sig_highres; n++)
+ ssch0->aspx_fic_used_in_sfb[n] = get_bits1(gb);
+ }
+
+ if (get_bits1(gb)) {
+ for (int n = 0; n < ssch0->num_sbg_sig_highres; n++)
+ ssch1->aspx_fic_used_in_sfb[n] = get_bits1(gb);
+ }
+ }
+
+ for (int n = 0; n < s->num_aspx_timeslots; n++)
+ ssch0->aspx_tic_used_in_slot[n] = ssch1->aspx_tic_used_in_slot[n] = 0;
+
+ if (get_bits1(gb)) {
+ int aspx_tic_copy = get_bits1(gb);
+
+ if (aspx_tic_copy == 0) {
+ aspx_tic_left = get_bits1(gb);
+ aspx_tic_right = get_bits1(gb);
+ }
+
+ if (aspx_tic_copy || aspx_tic_left) {
+ for (int n = 0; n < s->num_aspx_timeslots; n++)
+ ssch0->aspx_tic_used_in_slot[n] = get_bits1(gb);
+ }
+
+ if (aspx_tic_right) {
+ for (int n = 0; n < s->num_aspx_timeslots; n++)
+ ssch1->aspx_tic_used_in_slot[n] = get_bits1(gb);
+ }
+
+ if (aspx_tic_copy) {
+ for (int n = 0; n < s->num_aspx_timeslots; n++)
+ ssch1->aspx_tic_used_in_slot[n] = ssch0->aspx_tic_used_in_slot[n];
+ }
+ }
+
+ return 0;
+}
+
+static VLC *get_aspx_hcb(int data_type, int quant_mode, int stereo_mode, int hcb_type)
+{
+ VLC *aspx_cb;
+
+ if (data_type == DT_SIGNAL)
+ aspx_cb = &aspx_codebook_signal_vlc[stereo_mode][quant_mode][hcb_type];
+ else // NOISE
+ aspx_cb = &aspx_codebook_noise_vlc[stereo_mode][hcb_type];
+
+ return aspx_cb;
+}
+
+static int get_aspx_off(int data_type, int quant_mode, int stereo_mode, int hcb_type)
+{
+ int off;
+
+ if (data_type == DT_SIGNAL)
+ off = aspx_codebook_signal_off[stereo_mode][quant_mode][hcb_type];
+ else // NOISE
+ off = aspx_codebook_noise_off[stereo_mode][hcb_type];
+
+ return off;
+}
+
+static int aspx_huff_data(AC4DecodeContext *s,
+ int data_type, int num_sbg,
+ int quant_mode, int stereo_mode,
+ int direction, int *data)
+{
+ GetBitContext *gb = &s->gbc;
+ VLC *aspx_cb;
+ int aspx_off;
+
+ if (direction == 0) { // FREQ
+ aspx_cb = get_aspx_hcb(data_type, quant_mode, stereo_mode, F0);
+ aspx_off = get_aspx_off(data_type, quant_mode, stereo_mode, F0);
+ data[0] = get_vlc2(gb, aspx_cb->table, aspx_cb->bits, 3);
+ if (data[0] < 0)
+ return AVERROR_INVALIDDATA;
+ data[0] -= aspx_off;
+ aspx_cb = get_aspx_hcb(data_type, quant_mode, stereo_mode, DF);
+ aspx_off = get_aspx_off(data_type, quant_mode, stereo_mode, DF);
+ for (int i = 1; i < num_sbg; i++) {
+ data[i] = get_vlc2(gb, aspx_cb->table, aspx_cb->bits, 3);
+ if (data[i] < 0)
+ return AVERROR_INVALIDDATA;
+ data[i] -= aspx_off;
+ }
+ } else { // TIME
+ aspx_cb = get_aspx_hcb(data_type, quant_mode, stereo_mode, DT);
+ aspx_off = get_aspx_off(data_type, quant_mode, stereo_mode, DT);
+ for (int i = 0; i < num_sbg; i++) {
+ data[i] = get_vlc2(gb, aspx_cb->table, aspx_cb->bits, 3);
+ if (data[i] < 0)
+ return AVERROR_INVALIDDATA;
+ data[i] -= aspx_off;
+ }
+ }
+
+ return 0;
+}
+
+static int aspx_ec_data(AC4DecodeContext *s,
+ Substream *ss,
+ SubstreamChannel *ssch,
+ int data_type, int num_env,
+ uint8_t *freq_res, int quant_mode,
+ int stereo_mode, int *direction)
+{
+ int dir, num_sbg, ret;
+
+ for (int env = 0; env < num_env; env++) {
+ if (data_type == DT_SIGNAL) {
+ if (freq_res[env])
+ num_sbg = ssch->num_sbg_sig_highres;
+ else
+ num_sbg = ssch->num_sbg_sig_lowres;
+ } else {
+ num_sbg = ssch->num_sbg_noise;
+ }
+ dir = direction[env];
+ ret = aspx_huff_data(s, data_type, num_sbg, quant_mode, stereo_mode, dir,
+ ssch->aspx_data[data_type][env]);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int is_element_of_sbg_patches(int sbg_lim_sbg, int *sbg_patches,
+ int num_sbg_patches)
+{
+ for (int i = 0; i <= num_sbg_patches; i++) {
+ if (sbg_patches[i] == sbg_lim_sbg)
+ return 1;
+ }
+
+ return 0;
+}
+
+static void remove_element(int *sbg_lim, int num_sbg_lim, int sbg)
+{
+ for (int i = sbg; i < num_sbg_lim; i++)
+ sbg_lim[i] = sbg_lim[i + 1];
+}
+
+static int cmpints(const void *p1, const void *p2)
+{
+ int left = *(const int *)p1;
+ int right = *(const int *)p2;
+ return FFDIFFSIGN(left, right);
+}
+
+static int aspx_elements(AC4DecodeContext *s, Substream *ss, SubstreamChannel *ssch)
+{
+ int master_reset = (ss->prev_aspx_start_freq != ss->aspx_start_freq) +
+ (ss->prev_aspx_stop_freq != ss->aspx_stop_freq) +
+ (ss->prev_aspx_master_freq_scale != ss->aspx_master_freq_scale);
+ int sb, sbg = 0, goal_sb, msb, usb;
+ int source_band_low;
+ int idx[6];
+
+ if (master_reset) {
+ if (ss->aspx_master_freq_scale == 1) {
+ ssch->num_sbg_master = 22 - 2 * ss->aspx_start_freq - 2 * ss->aspx_stop_freq;
+ for (int sbg = 0; sbg <= ssch->num_sbg_master; sbg++) {
+ ssch->sbg_master[sbg] = sbg_template_highres[2 * ss->aspx_start_freq + sbg];
+ }
+ } else {
+ ssch->num_sbg_master = 20 - 2 * ss->aspx_start_freq - 2 * ss->aspx_stop_freq;
+ for (int sbg = 0; sbg <= ssch->num_sbg_master; sbg++) {
+ ssch->sbg_master[sbg] = sbg_template_lowres[2 * ss->aspx_start_freq + sbg];
+ }
+ }
+ }
+
+ ssch->sba = ssch->sbg_master[0];
+ ssch->sbz = ssch->sbg_master[ssch->num_sbg_master];
+
+ ssch->num_sbg_sig_highres = ssch->num_sbg_master - ssch->aspx_xover_subband_offset;
+ for (int sbg = 0; sbg <= ssch->num_sbg_sig_highres; sbg++)
+ ssch->sbg_sig_highres[sbg] = ssch->sbg_master[sbg + ssch->aspx_xover_subband_offset];
+
+ ssch->sbx = ssch->sbg_sig_highres[0];
+ ssch->num_sb_aspx = ssch->sbg_sig_highres[ssch->num_sbg_sig_highres] - ssch->sbx;
+
+ ssch->num_sbg_sig_lowres = ssch->num_sbg_sig_highres - floorf(ssch->num_sbg_sig_highres / 2.);
+ ssch->sbg_sig_lowres[0] = ssch->sbg_sig_highres[0];
+ if ((ssch->num_sbg_sig_highres & 1) == 0) {
+ for (int sbg = 1; sbg <= ssch->num_sbg_sig_lowres; sbg++)
+ ssch->sbg_sig_lowres[sbg] = ssch->sbg_sig_highres[2*sbg];
+ } else {
+ for (int sbg = 1; sbg <= ssch->num_sbg_sig_lowres; sbg++)
+ ssch->sbg_sig_lowres[sbg] = ssch->sbg_sig_highres[2*sbg-1];
+ }
+
+ ssch->num_sbg_sig[0] = ssch->num_sbg_sig_lowres;
+ ssch->num_sbg_sig[1] = ssch->num_sbg_sig_highres;
+
+ ssch->num_sbg_noise = FFMAX(1, floorf(ss->aspx_noise_sbg * log2f(ssch->sbz / (float)ssch->sbx) + 0.5));
+ idx[0] = 0;
+ ssch->sbg_noise[0] = ssch->sbg_sig_lowres[0];
+ for (int sbg = 1; sbg <= ssch->num_sbg_noise; sbg++) {
+ idx[sbg] = idx[sbg-1];
+ idx[sbg] += floorf((ssch->num_sbg_sig_lowres - idx[sbg - 1]) / (float)(ssch->num_sbg_noise + 1 - sbg));
+ ssch->sbg_noise[sbg] = ssch->sbg_sig_lowres[idx[sbg]];
+ }
+
+ msb = ssch->sba;
+ usb = ssch->sbx;
+ ssch->num_sbg_patches = 0;
+ if (s->fs_index)
+ goal_sb = 43;
+ else
+ goal_sb = 46;
+ if (ss->aspx_master_freq_scale == 1)
+ source_band_low = 4;
+ else
+ source_band_low = 2;
+
+ if (goal_sb < ssch->sbx + ssch->num_sb_aspx) {
+ for (int i = 0, sbg = 0; ssch->sbg_master[i] < goal_sb; i++)
+ sbg = i + 1;
+ } else {
+ sbg = ssch->num_sbg_master;
+ }
+
+ do {
+ int odd, j = sbg;
+ sb = ssch->sbg_master[j];
+ odd = (sb - 2 + ssch->sba) % 2;
+
+ while (sb > ( ssch->sba - source_band_low + msb - odd )) {
+ j--;
+ sb = ssch->sbg_master[j];
+ odd = (sb - 2 + ssch->sba) % 2;
+ }
+
+ ssch->sbg_patch_num_sb[ssch->num_sbg_patches] = FFMAX(sb - usb, 0);
+ ssch->sbg_patch_start_sb[ssch->num_sbg_patches] = ssch->sba - odd - FFMAX(sb - usb, 0);
+ if (ssch->sbg_patch_num_sb[ssch->num_sbg_patches] > 0) {
+ usb = sb;
+ msb = sb;
+ ssch->num_sbg_patches++;
+ } else {
+ msb = ssch->sbx;
+ }
+
+ if (ssch->sbg_master[sbg] - sb < 3)
+ sbg = ssch->num_sbg_master;
+ } while (sb != (ssch->sbx + ssch->num_sb_aspx));
+
+ if ((ssch->sbg_patch_num_sb[ssch->num_sbg_patches - 1] < 3) && (ssch->num_sbg_patches > 1))
+ ssch->num_sbg_patches--;
+
+ ssch->sbg_patches[0] = ssch->sbx;
+ for (int i = 1; i <= ssch->num_sbg_patches; i++)
+ ssch->sbg_patches[i] = ssch->sbg_patches[i-1] + ssch->sbg_patch_num_sb[i-1];
+
+ /* Copy sbg_sig_lowres into lower part of limiter table */
+ for (int sbg = 0; sbg <= ssch->num_sbg_sig_lowres; sbg++)
+ ssch->sbg_lim[sbg] = ssch->sbg_sig_lowres[sbg];
+
+ /* Copy patch borders into higher part of limiter table */
+ for (int sbg = 1; sbg < ssch->num_sbg_patches; sbg++)
+ ssch->sbg_lim[sbg + ssch->num_sbg_sig_lowres] = ssch->sbg_patches[sbg];
+
+ /* Sort patch borders + low res sbg into temporary limiter table */
+ ssch->num_sbg_lim = ssch->num_sbg_sig_lowres + ssch->num_sbg_patches - 1;
+ AV_QSORT(ssch->sbg_lim, ssch->num_sbg_lim + 1, int, cmpints);
+ sbg = 1;
+
+ while (sbg <= ssch->num_sbg_lim) {
+ float num_octaves = log2(ssch->sbg_lim[sbg] / (float)ssch->sbg_lim[sbg - 1]);
+
+ if (num_octaves < 0.245) {
+ if (ssch->sbg_lim[sbg] == ssch->sbg_lim[sbg-1]) {
+ remove_element(ssch->sbg_lim, ssch->num_sbg_lim, sbg);
+ ssch->num_sbg_lim--;
+ continue;
+ } else {
+ if (is_element_of_sbg_patches(ssch->sbg_lim[sbg],
+ ssch->sbg_patches,
+ ssch->num_sbg_patches)) {
+ if (is_element_of_sbg_patches(ssch->sbg_lim[sbg - 1],
+ ssch->sbg_patches,
+ ssch->num_sbg_patches)) {
+ sbg++;
+ continue;
+ } else {
+ remove_element(ssch->sbg_lim, ssch->num_sbg_lim, sbg - 1);
+ ssch->num_sbg_lim--;
+ continue;
+ }
+ } else {
+ remove_element(ssch->sbg_lim, ssch->num_sbg_lim, sbg);
+ ssch->num_sbg_lim--;
+ continue;
+ }
+ }
+ } else {
+ sbg++;
+ continue;
+ }
+ }
+
+ return 0;
+}
+
+static int aspx_data_2ch(AC4DecodeContext *s, Substream *ss,
+ SubstreamChannel *ssch0, SubstreamChannel *ssch1,
+ int iframe)
+{
+ GetBitContext *gb = &s->gbc;
+ int ret;
+
+ if (iframe) {
+ ssch0->aspx_xover_subband_offset = get_bits(gb, 3);
+ ssch1->aspx_xover_subband_offset = ssch0->aspx_xover_subband_offset;
+ }
+
+ aspx_elements(s, ss, ssch0);
+ aspx_elements(s, ss, ssch1);
+
+ ret = aspx_framing(s, ss, ssch0, iframe);
+ if (ret < 0)
+ return ret;
+
+ ssch0->aspx_qmode_env = ssch1->aspx_qmode_env = ss->aspx_quant_mode_env;
+ if (ssch0->aspx_int_class == FIXFIX && ssch0->aspx_num_env == 1)
+ ssch0->aspx_qmode_env = ssch1->aspx_qmode_env = 0;
+
+ ssch0->aspx_balance = ssch1->aspx_balance = get_bits1(gb);
+
+ if (ssch0->aspx_balance == 0) {
+ ret = aspx_framing(s, ss, ssch1, iframe);
+ if (ret < 0)
+ return ret;
+ ssch1->aspx_qmode_env = ss->aspx_quant_mode_env;
+ if (ssch1->aspx_int_class == FIXFIX && ssch1->aspx_num_env == 1)
+ ssch1->aspx_qmode_env = 0;
+ } else {
+ ssch1->aspx_num_env = ssch0->aspx_num_env;
+ ssch1->aspx_num_noise = ssch0->aspx_num_noise;
+ memcpy(&ssch1->atsg_freqres, &ssch0->atsg_freqres, sizeof(ssch0->atsg_freqres));
+ }
+
+ aspx_delta_dir(s, ssch0);
+ aspx_delta_dir(s, ssch1);
+ aspx_hfgen_iwc_2ch(s, ss, ssch0, ssch1, ssch0->aspx_balance);
+
+ ret = aspx_ec_data(s, ss, ssch0, DT_SIGNAL,
+ ssch0->aspx_num_env,
+ ssch0->atsg_freqres,
+ ssch0->aspx_qmode_env,
+ SM_LEVEL,
+ ssch0->aspx_sig_delta_dir);
+ if (ret < 0)
+ return ret;
+ ret = aspx_ec_data(s, ss, ssch1, DT_SIGNAL,
+ ssch1->aspx_num_env,
+ ssch1->atsg_freqres,
+ ssch1->aspx_qmode_env,
+ ssch0->aspx_balance ? SM_BALANCE : SM_LEVEL,
+ ssch1->aspx_sig_delta_dir);
+ if (ret < 0)
+ return ret;
+ ret = aspx_ec_data(s, ss, ssch0, DT_NOISE,
+ ssch0->aspx_num_noise,
+ 0,
+ 0,
+ SM_LEVEL,
+ ssch0->aspx_noise_delta_dir);
+ if (ret < 0)
+ return ret;
+ ret = aspx_ec_data(s, ss, ssch1, DT_NOISE,
+ ssch1->aspx_num_noise,
+ 0,
+ 0,
+ ssch0->aspx_balance ? SM_BALANCE : SM_LEVEL,
+ ssch1->aspx_noise_delta_dir);
+
+ return ret;
+}
+
+static int aspx_hfgen_iwc_1ch(AC4DecodeContext *s, Substream *ss,
+ SubstreamChannel *ssch)
+{
+ GetBitContext *gb = &s->gbc;
+
+ memcpy(ssch->aspx_tna_mode_prev, ssch->aspx_tna_mode, sizeof(ssch->aspx_tna_mode));
+
+ for (int n = 0; n < ssch->num_sbg_noise; n++)
+ ssch->aspx_tna_mode[n] = get_bits(gb, 2);
+ if (get_bits1(gb)) {
+ for (int n = 0; n < ssch->num_sbg_sig_highres; n++)
+ ssch->aspx_add_harmonic[n] = get_bits1(gb);
+ }
+
+ for (int n = 0; n < ssch->num_sbg_sig_highres; n++)
+ ssch->aspx_fic_used_in_sfb[n] = 0;
+
+ if (get_bits1(gb)) {
+ for (int n = 0; n < ssch->num_sbg_sig_highres; n++)
+ ssch->aspx_fic_used_in_sfb[n] = get_bits1(gb);
+ }
+
+ for (int n = 0; n < s->num_aspx_timeslots; n++)
+ ssch->aspx_tic_used_in_slot[n] = 0;
+
+ if (get_bits1(gb)) {
+ for (int n = 0; n < s->num_aspx_timeslots; n++)
+ ssch->aspx_tic_used_in_slot[n] = get_bits1(gb);
+ }
+
+ return 0;
+}
+
+static int aspx_data_1ch(AC4DecodeContext *s, Substream *ss,
+ SubstreamChannel *ssch, int iframe)
+{
+ GetBitContext *gb = &s->gbc;
+ int ret;
+
+ if (iframe)
+ ssch->aspx_xover_subband_offset = get_bits(gb, 3);
+
+ ssch->aspx_balance = 0;
+
+ aspx_elements(s, ss, ssch);
+
+ ret = aspx_framing(s, ss, ssch, iframe);
+ if (ret < 0)
+ return ret;
+
+ ssch->aspx_qmode_env = ss->aspx_quant_mode_env;
+ if (ssch->aspx_int_class == FIXFIX && ssch->aspx_num_env == 1)
+ ssch->aspx_qmode_env = 0;
+
+ aspx_delta_dir(s, ssch);
+ aspx_hfgen_iwc_1ch(s, ss, ssch);
+
+ ret = aspx_ec_data(s, ss, ssch, DT_SIGNAL,
+ ssch->aspx_num_env,
+ ssch->atsg_freqres,
+ ssch->aspx_qmode_env,
+ 0,
+ ssch->aspx_sig_delta_dir);
+ if (ret < 0)
+ return ret;
+ ret = aspx_ec_data(s, ss, ssch, DT_NOISE,
+ ssch->aspx_num_noise,
+ 0,
+ 0,
+ 0,
+ ssch->aspx_noise_delta_dir);
+ return ret;
+}
+
+static int acpl_framing_data(AC4DecodeContext *s, Substream *ss,
+ SubstreamChannel *ssch)
+{
+ GetBitContext *gb = &s->gbc;
+
+ ssch->acpl_interpolation_type = get_bits1(gb);
+ ssch->acpl_num_param_sets_cod = get_bits1(gb);
+ if (ssch->acpl_interpolation_type) {
+ for (int ps = 0; ps < ssch->acpl_num_param_sets_cod + 1; ps++)
+ ssch->acpl_param_timeslot[ps] = get_bits(gb, 5);
+ }
+
+ return 0;
+}
+
+static VLC *get_acpl_hcb(int data_type, int quant_mode, int hcb_type)
+{
+ VLC *acpl_cb;
+
+ acpl_cb = &acpl_codebook_vlc[data_type][quant_mode][hcb_type];
+
+ return acpl_cb;
+}
+
+static int acpl_huff_data(AC4DecodeContext *s,
+ int data_type, int data_bands,
+ int start_band, int quant_mode,
+ int *data)
+{
+ GetBitContext *gb = &s->gbc;
+ int diff_type;
+ VLC *acpl_cb;
+
+ switch (data_type) {
+ case ALPHA1:
+ case ALPHA2:
+ data_type = 0;
+ break;
+ case BETA1:
+ case BETA2:
+ data_type = 1;
+ break;
+ case BETA3:
+ data_type = 2;
+ break;
+ default:
+ data_type = 3;
+ break;
+ };
+
+ diff_type = get_bits1(gb);
+ if (diff_type == 0) { // DIFF_FREQ
+ acpl_cb = get_acpl_hcb(data_type, quant_mode, F0);
+ data[start_band] = get_vlc2(gb, acpl_cb->table, acpl_cb->bits, 3);
+ if (data[start_band] < 0)
+ return AVERROR_INVALIDDATA;
+ acpl_cb = get_acpl_hcb(data_type, quant_mode, DF);
+ for (int i = start_band + 1; i < data_bands; i++) {
+ data[i] = get_vlc2(gb, acpl_cb->table, acpl_cb->bits, 3);
+ if (data[i] < 0)
+ return AVERROR_INVALIDDATA;
+ }
+ } else { // DIFF_TIME
+ acpl_cb = get_acpl_hcb(data_type, quant_mode, DT);
+ for (int i = start_band; i < data_bands; i++) {
+ data[i] = get_vlc2(gb, acpl_cb->table, acpl_cb->bits, 3);
+ if (data[i] < 0)
+ return AVERROR_INVALIDDATA;
+ }
+ }
+
+ return 0;
+}
+
+static int acpl_ec_data(AC4DecodeContext *s, Substream *ss,
+ SubstreamChannel *ssch,
+ int data_type, int data_bands,
+ int start_band, int quant_mode)
+{
+ int ret;
+
+ for (int ps = 0; ps < ssch->acpl_num_param_sets_cod + 1; ps++) {
+ ret = acpl_huff_data(s, data_type, data_bands,
+ start_band, quant_mode,
+ ssch->acpl_data[data_type]);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int acpl_data_2ch(AC4DecodeContext *s, Substream *ss,
+ SubstreamChannel *ssch0,
+ SubstreamChannel *ssch1)
+{
+ int ret, num_bands, st;
+
+ acpl_framing_data(s, ss, ssch0);
+
+ num_bands = acpl_num_param_bands[ss->acpl_num_param_bands_id];
+ st = ss->acpl_param_band;
+
+ ret = acpl_ec_data(s, ss, ssch0, ALPHA1, num_bands, st, ss->acpl_quant_mode[0]);
+ if (ret < 0)
+ return ret;
+ ret = acpl_ec_data(s, ss, ssch0, ALPHA2, num_bands, st, ss->acpl_quant_mode[0]);
+ if (ret < 0)
+ return ret;
+ ret = acpl_ec_data(s, ss, ssch0, BETA1, num_bands, st, ss->acpl_quant_mode[0]);
+ if (ret < 0)
+ return ret;
+ ret = acpl_ec_data(s, ss, ssch0, BETA2, num_bands, st, ss->acpl_quant_mode[0]);
+ if (ret < 0)
+ return ret;
+ ret = acpl_ec_data(s, ss, ssch0, BETA3, num_bands, st, ss->acpl_quant_mode[0]);
+ if (ret < 0)
+ return ret;
+ ret = acpl_ec_data(s, ss, ssch1, GAMMA1, num_bands, st, ss->acpl_quant_mode[1]);
+ if (ret < 0)
+ return ret;
+ ret = acpl_ec_data(s, ss, ssch1, GAMMA2, num_bands, st, ss->acpl_quant_mode[1]);
+ if (ret < 0)
+ return ret;
+ ret = acpl_ec_data(s, ss, ssch1, GAMMA3, num_bands, st, ss->acpl_quant_mode[1]);
+ if (ret < 0)
+ return ret;
+ ret = acpl_ec_data(s, ss, ssch1, GAMMA4, num_bands, st, ss->acpl_quant_mode[1]);
+ if (ret < 0)
+ return ret;
+ ret = acpl_ec_data(s, ss, ssch1, GAMMA5, num_bands, st, ss->acpl_quant_mode[1]);
+ if (ret < 0)
+ return ret;
+ ret = acpl_ec_data(s, ss, ssch1, GAMMA6, num_bands, st, ss->acpl_quant_mode[1]);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int acpl_data_1ch(AC4DecodeContext *s, Substream *ss,
+ SubstreamChannel *ssch)
+{
+ int ret, num_bands, start;
+
+ acpl_framing_data(s, ss, ssch);
+
+ num_bands = acpl_num_param_bands[ss->acpl_num_param_bands_id];
+ start = ss->acpl_param_band;
+
+ ret = acpl_ec_data(s, ss, ssch, ALPHA1, num_bands, start, ss->acpl_quant_mode[0]);
+ if (ret < 0)
+ return ret;
+
+ ret = acpl_ec_data(s, ss, ssch, BETA1, num_bands, start, ss->acpl_quant_mode[0]);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int channel_pair_element(AC4DecodeContext *s, int iframe)
+{
+ GetBitContext *gb = &s->gbc;
+ Substream *ss = &s->substream;
+ int spec_frontend;
+ int ret;
+
+ ss->codec_mode = get_bits(gb, 2);
+ if (iframe) {
+ if (ss->codec_mode != CM_SIMPLE)
+ aspx_config(s, ss);
+ if (ss->codec_mode == CM_ASPX_ACPL_1)
+ acpl_config_1ch(s, ss, ACPL_PARTIAL);
+ if (ss->codec_mode == CM_ASPX_ACPL_2)
+ acpl_config_1ch(s, ss, ACPL_FULL);
+ }
+
+ switch (ss->codec_mode) {
+ case CM_SIMPLE:
+ ret = stereo_data(s, ss, iframe);
+ if (ret < 0)
+ return ret;
+ break;
+ case CM_ASPX:
+ companding_control(s, ss, 2);
+ ret = stereo_data(s, ss, iframe);
+ if (ret < 0)
+ return ret;
+ ret = aspx_data_2ch(s, ss, &ss->ssch[0], &ss->ssch[1], iframe);
+ if (ret < 0)
+ return ret;
+ break;
+ case CM_ASPX_ACPL_1:
+ companding_control(s, ss, 1);
+ ss->mdct_stereo_proc[0] = get_bits1(gb);
+ if (ss->mdct_stereo_proc[0]) {
+ ss->spec_frontend_m = SF_ASF;
+ ss->spec_frontend_s = SF_ASF;
+ ret = sf_info(s, ss, &ss->ssch[0], SF_ASF, 1, 0);
+ if (ret < 0)
+ return ret;
+
+ memcpy(&ss->ssch[1].scp, &ss->ssch[0].scp, sizeof(ss->ssch[0].scp));
+ memcpy(&ss->ssch[1].sect_sfb_offset, &ss->ssch[0].sect_sfb_offset, sizeof(ss->ssch[0].sect_sfb_offset));
+ memcpy(&ss->ssch[1].offset2sfb, &ss->ssch[0].offset2sfb, sizeof(ss->ssch[0].offset2sfb));
+ memcpy(&ss->ssch[1].offset2g, &ss->ssch[0].offset2g, sizeof(ss->ssch[0].offset2g));
+ memcpy(&ss->ssch[1].win_offset, &ss->ssch[0].win_offset, sizeof(ss->ssch[0].win_offset));
+
+ ret = chparam_info(s, ss, &ss->ssch[0]);
+ if (ret < 0)
+ return ret;
+ } else {
+ ss->spec_frontend_m = get_bits1(gb);
+ ret = sf_info(s, ss, &ss->ssch[0], ss->spec_frontend_m, 0, 0);
+ if (ret < 0)
+ return ret;
+ ss->spec_frontend_s = get_bits1(gb);
+ ret = sf_info(s, ss, &ss->ssch[1], ss->spec_frontend_s, 0, 1);
+ if (ret < 0)
+ return ret;
+ }
+ ret = sf_data(s, ss, &ss->ssch[0], iframe, ss->spec_frontend_m);
+ if (ret < 0)
+ return ret;
+ ret = sf_data(s, ss, &ss->ssch[1], iframe, ss->spec_frontend_m);
+ if (ret < 0)
+ return ret;
+ ret = aspx_data_1ch(s, ss, &ss->ssch[0], iframe);
+ if (ret < 0)
+ return ret;
+ ret = acpl_data_1ch(s, ss, &ss->ssch[0]);
+ if (ret < 0)
+ return ret;
+ break;
+ case CM_ASPX_ACPL_2:
+ companding_control(s, ss, 1);
+ spec_frontend = get_bits1(gb);
+ ret = sf_info(s, ss, &ss->ssch[0], spec_frontend, 0, 0);
+ if (ret < 0)
+ return ret;
+ ret = sf_data(s, ss, &ss->ssch[0], iframe, spec_frontend);
+ if (ret < 0)
+ return ret;
+ ret = aspx_data_1ch(s, ss, &ss->ssch[0], iframe);
+ if (ret < 0)
+ return ret;
+ ret = acpl_data_1ch(s, ss, &ss->ssch[0]);
+ if (ret < 0)
+ return ret;
+ break;
+ }
+
+ return 0;
+}
+
+static int four_channel_data(AC4DecodeContext *s, Substream *ss, int iframe)
+{
+ int ret;
+
+ ret = sf_info(s, ss, &ss->ssch[0], SF_ASF, 0, 0);
+ if (ret < 0)
+ return ret;
+
+ for (int i = 1; i < 4; i++) {
+ memcpy(&ss->ssch[i], &ss->ssch[0], sizeof(ss->ssch[0]));
+ }
+
+ for (int i = 0; i < 4; i++) {
+ ret = chparam_info(s, ss, &ss->ssch[i]);
+ if (ret < 0)
+ return ret;
+ }
+
+ for (int i = 0; i < 4; i++) {
+ ret = sf_data(s, ss, &ss->ssch[i], iframe, SF_ASF);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int channel_element_7x(AC4DecodeContext *s, int channel_mode, int iframe)
+{
+ GetBitContext *gb = &s->gbc;
+ Substream *ss = &s->substream;
+ int ret = 0;
+
+ ss->codec_mode = get_bits(gb, 2);
+ if (iframe) {
+ if (ss->codec_mode != CM_SIMPLE)
+ aspx_config(s, ss);
+ if (ss->codec_mode == CM_ASPX_ACPL_1)
+ acpl_config_1ch(s, ss, ACPL_PARTIAL);
+ if (ss->codec_mode == CM_ASPX_ACPL_2)
+ acpl_config_1ch(s, ss, ACPL_FULL);
+ }
+
+ if (channel_mode == 6) {
+ av_assert0(0);
+ }
+
+ if (ss->codec_mode == CM_ASPX_ACPL_1 ||
+ ss->codec_mode == CM_ASPX_ACPL_2)
+ companding_control(s, ss, 5);
+
+ ss->coding_config = get_bits(gb, 2);
+ switch (ss->coding_config) {
+ case 0:
+ break;
+ case 1:
+ break;
+ case 2:
+ ret = four_channel_data(s, ss, iframe);
+ break;
+ default:
+ av_assert0(0);
+ }
+
+ return ret;
+}
+
+static int get_msfbl_bits(int transf_length)
+{
+ if (transf_length <= 2048 && transf_length >= 1536)
+ return 3;
+
+ return 2;
+}
+
+static int sf_info_lfe(AC4DecodeContext *s, Substream *ss,
+ SubstreamChannel *ssch)
+{
+ GetBitContext *gb = &s->gbc;
+ int n_msfbl_bits = get_msfbl_bits(s->frame_len_base);
+
+ ssch->scp.long_frame = 1;
+ ssch->scp.max_sfb[0] = get_bits(gb, n_msfbl_bits);
+ ssch->scp.num_window_groups = 1;
+
+ return asf_psy_elements(s, ss, ssch, 0);
+}
+
+static int mono_data(AC4DecodeContext *s, Substream *ss,
+ SubstreamChannel *ssch, int lfe, int iframe)
+{
+ GetBitContext *gb = &s->gbc;
+ int spec_frontend;
+ int ret;
+
+ if (lfe) {
+ spec_frontend = SF_ASF;
+ ret = sf_info_lfe(s, ss, ssch);
+ } else {
+ spec_frontend = get_bits1(gb);
+ ret = sf_info(s, ss, ssch, spec_frontend, 0, 0);
+ }
+ if (ret < 0)
+ return ret;
+ return sf_data(s, ss, ssch, iframe, spec_frontend);
+}
+
+static int three_channel_info(AC4DecodeContext *s, Substream *ss,
+ SubstreamChannel *ssch0,
+ SubstreamChannel *ssch1,
+ SubstreamChannel *ssch2)
+{
+ GetBitContext *gb = &s->gbc;
+ int ret;
+
+ ss->chel_matsel = get_bits(gb, 4);
+ ret = chparam_info(s, ss, ssch0);
+ if (ret < 0)
+ return ret;
+ return chparam_info(s, ss, ssch1);
+}
+
+static int three_channel_data(AC4DecodeContext *s, Substream *ss,
+ SubstreamChannel *ssch0,
+ SubstreamChannel *ssch1,
+ SubstreamChannel *ssch2)
+{
+ int ret;
+
+ ret = sf_info(s, ss, ssch0, SF_ASF, 0, 0);
+ if (ret < 0)
+ return ret;
+
+ memcpy(&ssch1->scp, &ssch0->scp, sizeof(ss->ssch[0].scp));
+ memcpy(&ssch1->sect_sfb_offset, &ssch0->sect_sfb_offset, sizeof(ss->ssch[0].sect_sfb_offset));
+ memcpy(&ssch1->offset2sfb, &ssch0->offset2sfb, sizeof(ss->ssch[0].offset2sfb));
+ memcpy(&ssch1->offset2g, &ssch0->offset2g, sizeof(ss->ssch[0].offset2g));
+ memcpy(&ssch1->win_offset, &ssch0->win_offset, sizeof(ss->ssch[0].win_offset));
+
+ memcpy(&ssch2->scp, &ssch0->scp, sizeof(ss->ssch[0].scp));
+ memcpy(&ssch2->sect_sfb_offset, &ssch0->sect_sfb_offset, sizeof(ss->ssch[0].sect_sfb_offset));
+ memcpy(&ssch2->offset2sfb, &ssch0->offset2sfb, sizeof(ss->ssch[0].offset2sfb));
+ memcpy(&ssch2->offset2g, &ssch0->offset2g, sizeof(ss->ssch[0].offset2g));
+ memcpy(&ssch2->win_offset, &ssch0->win_offset, sizeof(ss->ssch[0].win_offset));
+
+ ret = three_channel_info(s, ss, ssch0, ssch1, ssch2);
+ if (ret < 0)
+ return ret;
+ ret = sf_data(s, ss, ssch0, 0, SF_ASF);
+ if (ret < 0)
+ return ret;
+ ret = sf_data(s, ss, ssch1, 0, SF_ASF);
+ if (ret < 0)
+ return ret;
+ ret = sf_data(s, ss, ssch2, 0, SF_ASF);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int two_channel_data(AC4DecodeContext *s, Substream *ss,
+ SubstreamChannel *ssch0,
+ SubstreamChannel *ssch1,
+ int x)
+{
+ GetBitContext *gb = &s->gbc;
+ int ret;
+
+ ss->mdct_stereo_proc[x] = get_bits1(gb);
+ if (ss->mdct_stereo_proc[x]) {
+ ret = sf_info(s, ss, ssch0, SF_ASF, 0, 0);
+ if (ret < 0)
+ return ret;
+
+ memcpy(&ssch1->scp, &ssch0->scp, sizeof(ss->ssch[0].scp));
+ memcpy(&ssch1->sect_sfb_offset, &ssch0->sect_sfb_offset, sizeof(ss->ssch[0].sect_sfb_offset));
+ memcpy(&ssch1->offset2sfb, &ssch0->offset2sfb, sizeof(ss->ssch[0].offset2sfb));
+ memcpy(&ssch1->offset2g, &ssch0->offset2g, sizeof(ss->ssch[0].offset2g));
+ memcpy(&ssch1->win_offset, &ssch0->win_offset, sizeof(ss->ssch[0].win_offset));
+
+ ret = chparam_info(s, ss, ssch0);
+ if (ret < 0)
+ return ret;
+ } else {
+ ret = sf_info(s, ss, ssch0, SF_ASF, 0, 0);
+ if (ret < 0)
+ return ret;
+ ret = sf_info(s, ss, ssch1, SF_ASF, 0, 0);
+ if (ret < 0)
+ return ret;
+ }
+ ret = sf_data(s, ss, ssch0, 0, SF_ASF);
+ if (ret < 0)
+ return ret;
+ ret = sf_data(s, ss, ssch1, 0, SF_ASF);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int five_channel_info(AC4DecodeContext *s, Substream *ss)
+{
+ GetBitContext *gb = &s->gbc;
+ int ret;
+
+ ss->chel_matsel = get_bits(gb, 4);
+
+ for (int i = 0; i < 5; i++) {
+ ret = chparam_info(s, ss, &ss->ssch[i]);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int five_channel_data(AC4DecodeContext *s, Substream *ss, int iframe)
+{
+ int ret;
+
+ ret = sf_info(s, ss, &ss->ssch[0], SF_ASF, 0, 0);
+ if (ret < 0)
+ return ret;
+
+ for (int i = 1; i < 5; i++) {
+ memcpy(&ss->ssch[i], &ss->ssch[0], sizeof(ss->ssch[0]));
+ }
+
+ ret = five_channel_info(s, ss);
+ if (ret < 0)
+ return ret;
+
+ for (int i = 0; i < 5; i++) {
+ ret = sf_data(s, ss, &ss->ssch[i], 0, SF_ASF);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int channel_element_3x(AC4DecodeContext *s, int iframe)
+{
+ GetBitContext *gb = &s->gbc;
+ Substream *ss = &s->substream;
+ int ret;
+
+ ss->codec_mode = get_bits1(gb);
+ if (ss->codec_mode == CM_ASPX) {
+ if (iframe)
+ aspx_config(s, ss);
+ companding_control(s, ss, 3);
+ }
+
+ ss->coding_config = get_bits1(gb);
+ switch (ss->coding_config) {
+ case 0:
+ ret = stereo_data(s, ss, iframe);
+ if (ret < 0)
+ return ret;
+ ret = mono_data(s, ss, &ss->ssch[2], 0, iframe);
+ if (ret < 0)
+ return ret;
+ break;
+ case 1:
+ ret = three_channel_data(s, ss,
+ &ss->ssch[0],
+ &ss->ssch[1],
+ &ss->ssch[2]);
+ if (ret < 0)
+ return ret;
+ break;
+ }
+
+ if (ss->codec_mode == CM_ASPX) {
+ ret = aspx_data_2ch(s, ss, &ss->ssch[0], &ss->ssch[1], iframe);
+ if (ret < 0)
+ return ret;
+ ret = aspx_data_1ch(s, ss, &ss->ssch[2], iframe);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int channel_element_5x(AC4DecodeContext *s, int lfe, int iframe)
+{
+ GetBitContext *gb = &s->gbc;
+ Substream *ss = &s->substream;
+ int ret = 0;
+
+ ss->codec_mode = get_bits(gb, 3);
+ if (iframe) {
+ if (ss->codec_mode != CM_SIMPLE)
+ aspx_config(s, ss);
+ if (ss->codec_mode == CM_ASPX_ACPL_1)
+ acpl_config_1ch(s, ss, ACPL_PARTIAL);
+ if (ss->codec_mode == CM_ASPX_ACPL_2)
+ acpl_config_1ch(s, ss, ACPL_FULL);
+ if (ss->codec_mode == CM_ASPX_ACPL_3)
+ acpl_config_2ch(s, ss);
+ }
+
+ if (lfe) {
+ ret = mono_data(s, ss, &ss->ssch[5], 1, iframe);
+ if (ret < 0)
+ return ret;
+ }
+
+ switch (ss->codec_mode) {
+ case CM_SIMPLE:
+ case CM_ASPX:
+ if (ss->codec_mode == CM_ASPX)
+ companding_control(s, ss, 5);
+
+ ss->coding_config = get_bits(gb, 2);
+ switch (ss->coding_config) {
+ case 0:
+ ss->mode_2ch = get_bits1(gb);
+ ret = two_channel_data(s, ss, &ss->ssch[0], &ss->ssch[1], 0);
+ if (ret < 0)
+ return ret;
+ ret = two_channel_data(s, ss, &ss->ssch[2], &ss->ssch[3], 1);
+ if (ret < 0)
+ return ret;
+ ret = mono_data(s, ss, &ss->ssch[4], 0, iframe);
+ if (ret < 0)
+ return ret;
+ break;
+ case 1:
+ ret = three_channel_data(s, ss, &ss->ssch[0], &ss->ssch[1], &ss->ssch[2]);
+ if (ret < 0)
+ return ret;
+ ret = two_channel_data(s, ss, &ss->ssch[3], &ss->ssch[4], 0);
+ if (ret < 0)
+ return ret;
+ break;
+ case 2:
+ ret = four_channel_data(s, ss, iframe);
+ if (ret < 0)
+ return ret;
+ ret = mono_data(s, ss, &ss->ssch[4], 0, iframe);
+ if (ret < 0)
+ return ret;
+ break;
+ case 3:
+ ret = five_channel_data(s, ss, iframe);
+ if (ret < 0)
+ return ret;
+ break;
+ }
+
+ if (ss->codec_mode == CM_ASPX) {
+ ret = aspx_data_2ch(s, ss, &ss->ssch[0], &ss->ssch[1], iframe);
+ if (ret < 0)
+ return ret;
+ ret = aspx_data_2ch(s, ss, &ss->ssch[2], &ss->ssch[3], iframe);
+ if (ret < 0)
+ return ret;
+ ret = aspx_data_1ch(s, ss, &ss->ssch[4], iframe);
+ if (ret < 0)
+ return ret;
+ }
+ break;
+ case CM_ASPX_ACPL_1:
+ case CM_ASPX_ACPL_2:
+ companding_control(s, ss, 3);
+ ss->coding_config = get_bits1(gb);
+ if (ss->coding_config)
+ ret = three_channel_data(s, ss, &ss->ssch[0], &ss->ssch[1], &ss->ssch[2]);
+ else
+ ret = two_channel_data(s, ss, &ss->ssch[0], &ss->ssch[1], 0);
+ if (ret < 0)
+ return ret;
+
+ if (ss->codec_mode == CM_ASPX_ACPL_1) {
+ ss->max_sfb_master = get_bits(gb, 5); // XXX
+ ret = chparam_info(s, ss, &ss->ssch[3]);
+ if (ret < 0)
+ return ret;
+ ret = chparam_info(s, ss, &ss->ssch[4]);
+ if (ret < 0)
+ return ret;
+ ret = sf_data(s, ss, &ss->ssch[3], iframe, SF_ASF);
+ if (ret < 0)
+ return ret;
+ ret = sf_data(s, ss, &ss->ssch[4], iframe, SF_ASF);
+ if (ret < 0)
+ return ret;
+ }
+ if (ss->coding_config == 0) {
+ ret = mono_data(s, ss, &ss->ssch[2], 0, iframe);
+ if (ret < 0)
+ return ret;
+ }
+
+ ret = aspx_data_2ch(s, ss, &ss->ssch[0], &ss->ssch[1], iframe);
+ if (ret < 0)
+ return ret;
+ ret = aspx_data_1ch(s, ss, &ss->ssch[2], iframe);
+ if (ret < 0)
+ return ret;
+ ret = acpl_data_1ch(s, ss, &ss->ssch[0]);
+ if (ret < 0)
+ return ret;
+ ret = acpl_data_1ch(s, ss, &ss->ssch[1]);
+ if (ret < 0)
+ return ret;
+ break;
+ case CM_ASPX_ACPL_3:
+ companding_control(s, ss, 2);
+ ret = stereo_data(s, ss, iframe);
+ if (ret < 0)
+ return ret;
+ ret = aspx_data_2ch(s, ss, &ss->ssch[0], &ss->ssch[1], iframe);
+ if (ret < 0)
+ return ret;
+ ret = acpl_data_2ch(s, ss, &ss->ssch[0], &ss->ssch[1]);
+ if (ret < 0)
+ return ret;
+ break;
+ default:
+ av_assert0(0);
+ }
+
+ return ret;
+}
+
+static int single_channel_element(AC4DecodeContext *s, int iframe)
+{
+ GetBitContext *gb = &s->gbc;
+ Substream *ss = &s->substream;
+ int ret = 0;
+
+ ss->codec_mode = get_bits1(gb);
+ if (iframe) {
+ if (ss->codec_mode == CM_ASPX)
+ aspx_config(s, ss);
+ }
+ if (ss->codec_mode == CM_SIMPLE) {
+ ret = mono_data(s, ss, &ss->ssch[0], 0, iframe);
+ } else {
+ companding_control(s, ss, 1);
+ ret = mono_data(s, ss, &ss->ssch[0], 0, iframe);
+ if (ret < 0)
+ return ret;
+ ret = aspx_data_1ch(s, ss, &ss->ssch[0], iframe);
+ }
+
+ return ret;
+}
+
+static int audio_data(AC4DecodeContext *s, int channel_mode, int iframe)
+{
+ int ret = 0;
+
+ switch (channel_mode) {
+ case 0:
+ ret = single_channel_element(s, iframe);
+ break;
+ case 1:
+ ret = channel_pair_element(s, iframe);
+ break;
+ case 2:
+ ret = channel_element_3x(s, iframe);
+ break;
+ case 3:
+ ret = channel_element_5x(s, 0, iframe);
+ break;
+ case 4:
+ ret = channel_element_5x(s, 1, iframe);
+ break;
+ case 5:
+ ret = channel_element_7x(s, channel_mode, iframe);
+ break;
+ default:
+ av_assert0(0);
+ break;
+ }
+
+ return ret;
+}
+
+static int further_loudness_info(AC4DecodeContext *s, SubstreamInfo *ssi)
+{
+ GetBitContext *gb = &s->gbc;
+ Metadata *m = &ssi->meta;
+
+ m->loudness_version = get_bits(gb, 2);
+ if (m->loudness_version == 3)
+ m->loudness_version += get_bits(gb, 4);
+
+ m->loud_prac_type = get_bits(gb, 4);
+ if (m->loud_prac_type != 0) {
+ if (get_bits1(gb))
+ m->dialgate_prac_type = get_bits(gb, 3);
+ m->loudcorr_type = get_bits1(gb);
+ }
+
+ if (get_bits1(gb))
+ m->loudrelgat = get_bits(gb, 11);
+
+ if (get_bits1(gb)) {
+ m->loudspchgat = get_bits(gb, 11);
+ m->dialgate_prac_type = get_bits(gb, 3);
+ }
+
+ if (get_bits1(gb))
+ m->loudstrm3s = get_bits(gb, 11);
+
+ if (get_bits1(gb))
+ m->max_loudstrm3s = get_bits(gb, 11);
+
+ if (get_bits1(gb))
+ m->truepk = get_bits(gb, 11);
+
+ if (get_bits1(gb))
+ m->max_truepk = get_bits(gb, 11);
+
+ if (get_bits1(gb)) {
+ int prgmbndy_bit = 0;
+
+ m->prgmbndy = 1;
+ while (prgmbndy_bit == 0) {
+ m->prgmbndy <<= 1;
+ prgmbndy_bit = get_bits1(gb);
+ }
+
+ m->end_or_start = get_bits1(gb);
+ if (get_bits1(gb))
+ m->prgmbndy_offset = get_bits(gb, 11);
+ }
+
+ if (get_bits1(gb)) {
+ m->lra = get_bits(gb, 10);
+ m->lra_prac_type = get_bits(gb, 3);
+ }
+
+ if (get_bits1(gb))
+ m->loudmntry = get_bits(gb, 11);
+
+ if (get_bits1(gb))
+ m->max_loudmntry = get_bits(gb, 11);
+
+ if (get_bits1(gb)) {
+ int e_bits_size = get_bits(gb, 5);
+ if (e_bits_size == 31)
+ e_bits_size += variable_bits(gb, 4);
+ skip_bits_long(gb, e_bits_size);
+ }
+
+ return 0;
+}
+
+static int channel_mode_contains_lfe(int channel_mode)
+{
+ if (channel_mode == 4 ||
+ channel_mode == 6 ||
+ channel_mode == 8 ||
+ channel_mode == 10)
+ return 1;
+ return 0;
+}
+
+static int basic_metadata(AC4DecodeContext *s, SubstreamInfo *ssi)
+{
+ GetBitContext *gb = &s->gbc;
+ Metadata *m = &ssi->meta;
+
+ if (ssi->sus_ver == 0)
+ m->dialnorm_bits = get_bits(gb, 7);
+
+ if (get_bits1(gb)) {
+ if (get_bits1(gb))
+ further_loudness_info(s, ssi);
+ if (ssi->channel_mode == 1) {
+ if (get_bits1(gb)) {
+ m->pre_dmixtyp_2ch = get_bits(gb, 3);
+ m->phase90_info_2ch = get_bits(gb, 2);
+ }
+ }
+
+ if (ssi->channel_mode > 1) {
+ if (get_bits1(gb)) {
+ m->loro_center_mixgain = get_bits(gb, 3);
+ m->loro_surround_mixgain = get_bits(gb, 3);
+ if (get_bits1(gb))
+ m->loro_dmx_loud_corr = get_bits(gb, 5);
+ if (get_bits1(gb)) {
+ m->ltrt_center_mixgain = get_bits(gb, 3);
+ m->ltrt_surround_mixgain = get_bits(gb, 3);
+ }
+ if (get_bits1(gb))
+ m->ltrt_dmx_loud_corr = get_bits(gb, 5);
+ if (channel_mode_contains_lfe(ssi->channel_mode)) {
+ if (get_bits1(gb))
+ m->lfe_mixgain = get_bits(gb, 5);
+ }
+ m->preferred_dmx_method = get_bits(gb, 2);
+ }
+ if (ssi->channel_mode == 3 ||
+ ssi->channel_mode == 4) {
+ if (get_bits1(gb))
+ m->pre_dmixtyp_5ch = get_bits(gb, 3);
+ if (get_bits1(gb))
+ m->pre_upmixtyp_5ch = get_bits(gb, 4);
+ }
+
+ if (ssi->channel_mode >= 5 && ssi->channel_mode <= 10) {
+ if (get_bits1(gb)) {
+ if (ssi->channel_mode >= 5 && ssi->channel_mode <= 6) {
+ m->pre_upmixtyp_3_4 = get_bits(gb, 2);
+ } else if (ssi->channel_mode >= 9 && ssi->channel_mode <= 10) {
+ m->pre_upmixtyp_3_2_2 = get_bits(gb, 1);
+ }
+ }
+ }
+ m->phase90_info_mc = get_bits(gb, 2);
+ m->surround_attenuation_known = get_bits1(gb);
+ m->lfe_attenuation_known = get_bits1(gb);
+ }
+
+ if (get_bits1(gb))
+ m->dc_block_on = get_bits1(gb);
+ }
+ return 0;
+}
+
+static int extended_metadata(AC4DecodeContext *s)
+{
+ return 0;
+}
+
+static int drc_decoder_mode_config(AC4DecodeContext *s, SubstreamInfo *ssi)
+{
+ return 0;
+}
+
+static int drc_config(AC4DecodeContext *s, SubstreamInfo *ssi)
+{
+ GetBitContext *gb = &s->gbc;
+ Metadata *m = &ssi->meta;
+
+ m->drc_decoder_nr_modes = get_bits(gb, 3);
+ for (int i = 0; i <= m->drc_decoder_nr_modes; i++)
+ drc_decoder_mode_config(s, ssi);
+ m->drc_eac3_profile = get_bits(gb, 3);
+
+ return 0;
+}
+
+static int drc_data(AC4DecodeContext *s, SubstreamInfo *ssi)
+{
+ return 0;
+}
+
+static int drc_frame(AC4DecodeContext *s, SubstreamInfo *ssi, int iframe)
+{
+ GetBitContext *gb = &s->gbc;
+
+ if (get_bits1(gb)) {
+ if (iframe)
+ drc_config(s, ssi);
+
+ drc_data(s, ssi);
+ }
+
+ return 0;
+}
+
+static int dialog_enhancement(AC4DecodeContext *s, int iframe)
+{
+ return 0;
+}
+
+static int emdf_payloads_substream(AC4DecodeContext *s)
+{
+ return 0;
+}
+
+static int metadata(AC4DecodeContext *s, SubstreamInfo *ssi, int iframe)
+{
+ GetBitContext *gb = &s->gbc;
+ int tools_metadata_size;
+
+ basic_metadata(s, ssi);
+ extended_metadata(s);
+ tools_metadata_size = get_bits(gb, 7);
+ if (get_bits1(gb))
+ tools_metadata_size += variable_bits(gb, 3) << 7;
+
+ drc_frame(s, ssi, iframe);
+
+ dialog_enhancement(s, iframe);
+
+ if (get_bits1(gb))
+ emdf_payloads_substream(s);
+
+ return 0;
+}
+
+static int ac4_substream(AC4DecodeContext *s)
+{
+ GetBitContext *gb = &s->gbc;
+ int audio_size, offset, consumed;
+ int ret;
+
+ audio_size = get_bits(gb, 15);
+ if (get_bits1(gb))
+ audio_size += variable_bits(gb, 7) << 15;
+ if (audio_size > 131072)
+ return AVERROR_INVALIDDATA;
+
+ av_log(s->avctx, AV_LOG_DEBUG, "audio_size: %d\n", audio_size);
+
+ align_get_bits(gb);
+
+ offset = get_bits_count(gb) >> 3;
+ ret = audio_data(s, s->pinfo[0].ssinfo.channel_mode, s->pinfo[0].ssinfo.iframe[0]);
+ if (ret < 0)
+ return ret;
+
+ align_get_bits(gb);
+ consumed = (get_bits_count(gb) >> 3) - offset;
+ if (consumed > audio_size) {
+ av_log(s->avctx, AV_LOG_ERROR, "substream audio data overread: %d\n", consumed - audio_size);
+ return AVERROR_INVALIDDATA;
+ }
+ if (consumed < audio_size) {
+ int non_zero = 0;
+
+ for (int i = consumed; i < audio_size; i++)
+ non_zero += !!get_bits(gb, 8);
+ if (non_zero)
+ av_log(s->avctx, AV_LOG_WARNING, "substream audio data underread: %d\n", non_zero);
+ }
+
+ metadata(s, &s->pinfo[0].ssinfo, s->iframe_global);
+
+ align_get_bits(gb);
+
+ return 0;
+}
+
+static void spectral_reordering(AC4DecodeContext *s, SubstreamChannel *ssch)
+{
+ float *scaled_spec = ssch->scaled_spec;
+ float *spec_reord = ssch->spec_reord;
+ int *win_offset = ssch->win_offset;
+ int k, win;
+
+ k = 0;
+ win = 0;
+ memset(ssch->spec_reord, 0, sizeof(ssch->spec_reord));
+
+ for (int g = 0; g < ssch->scp.num_window_groups; g++) {
+ int transf_length_g = get_transf_length(s, ssch, g, NULL);
+ const uint16_t *sfb_offset = get_sfb_offset(transf_length_g);
+ int max_sfb = get_max_sfb(s, ssch, g);
+
+ for (int sfb = 0; sfb < max_sfb; sfb++) {
+ for (int w = 0; w < ssch->scp.num_win_in_group[g]; w++) {
+ for (int l = sfb_offset[sfb]; l < sfb_offset[sfb+1]; l++)
+ spec_reord[win_offset[win+w] + l] = scaled_spec[k++];
+ }
+ }
+ win += ssch->scp.num_win_in_group[g];
+ }
+}
+
+static int compute_window(AC4DecodeContext *s, float *w, int N,
+ int N_prev, int Nfull, int dir)
+{
+ const uint16_t *transf_lengths = transf_length_48khz[s->frame_len_base_idx];
+ float *kernel;
+ int i, idx, N_w, N_skip;
+
+ if (N <= N_prev)
+ N_w = N;
+ if (N > N_prev)
+ N_w = N_prev;
+
+ for (i = 0; i < 5; i++) {
+ if (transf_lengths[i] == N_w) {
+ idx = i;
+ break;
+ }
+ }
+
+ av_assert0(i < 5);
+
+ N_skip = (N - N_w) / 2;
+ kernel = s->kbd_window[s->frame_len_base_idx][idx];
+
+ for (int n = 0; n < N; n++) {
+ if (n >= 0 && n < N_skip)
+ w[n] = dir;
+ else if (n >= N_skip && n < N_w + N_skip)
+ w[n] = !dir ? kernel[n - N_skip] : kernel[N_w - n + N_skip - 1];
+ else if (n >= N_w + N_skip && n < N_w + 2 * N_skip)
+ w[n] = !dir;
+ else
+ av_assert0(0);
+ }
+
+ return 0;
+}
+
+static void scale_spec(AC4DecodeContext *s, int ch)
+{
+ Substream *ss = &s->substream;
+ SubstreamChannel *ssch = &ss->ssch[ch];
+ const float *quant_lut = s->quant_lut;
+
+ memset(ssch->scaled_spec, 0, sizeof(ssch->scaled_spec));
+
+ for (int k = 0; k < s->frame_len_base; k++) {
+ int x = ssch->quant_spec[k];
+ int sfb = ssch->offset2sfb[k];
+ int g = ssch->offset2g[k];
+
+ ssch->scaled_spec[k] = ssch->sf_gain[g][sfb] * copysignf(quant_lut[FFABS(x)], x) / 32768.f;
+ }
+}
+
+static int two_channel_processing(AC4DecodeContext *s, Substream *ss,
+ SubstreamChannel *ssch0,
+ SubstreamChannel *ssch1)
+{
+ int max_sfb_prev;
+ float sap_gain;
+
+ memset(&ss->alpha_q, 0, sizeof(ss->alpha_q));
+
+ max_sfb_prev = get_max_sfb(s, ssch0, 0);
+ for (int g = 0; g < ssch0->scp.num_window_groups; g++) {
+ int max_sfb_g = get_max_sfb(s, ssch0, g);
+
+ for (int sfb = 0; sfb < max_sfb_g; sfb++) {
+ float m[2][2];
+
+ if (ssch0->sap_mode == 0 ||
+ (ssch0->sap_mode == 1 && ssch0->ms_used[g][sfb] == 0)) {
+ m[0][0] = m[1][1] = 1;
+ m[0][1] = m[1][0] = 0;
+ } else if (ssch0->sap_mode == 2 ||
+ ((ssch0->sap_mode == 1 && ssch0->ms_used[g][sfb] == 1))) {
+ m[0][0] =
+ m[0][1] =
+ m[1][0] = 1;
+ m[1][1] = -1;
+ } else { // sap_mode == 3
+ if (ssch0->sap_coeff_used[g][sfb]) { // setup alpha_q[g][sfb]
+ if (sfb & 1) {
+ ss->alpha_q[g][sfb] = ss->alpha_q[g][sfb-1];
+ } else {
+ float delta = ssch0->dpcm_alpha_q[g][sfb] - 60;
+ int code_delta;
+
+ if ((g == 0) || (max_sfb_g != max_sfb_prev)) {
+ code_delta = 0;
+ } else {
+ code_delta = ssch0->delta_code_time;
+ }
+
+ if (code_delta) {
+ ss->alpha_q[g][sfb] = ss->alpha_q[g-1][sfb] + delta;
+ } else if (sfb == 0) {
+ ss->alpha_q[g][sfb] = delta;
+ } else {
+ ss->alpha_q[g][sfb] = ss->alpha_q[g][sfb-2] + delta;
+ }
+ }
+ // inverse quantize alpha_q[g][sfb]
+ sap_gain = ss->alpha_q[g][sfb] * 0.1f;
+ m[0][0] = 1 + sap_gain;
+ m[0][1] = 1;
+ m[1][0] = 1 - sap_gain;
+ m[1][1] = -1;
+ } else {
+ m[0][0] = 1;
+ m[0][1] = 0;
+ m[1][0] = 0;
+ m[1][1] = 1;
+ }
+ }
+
+ memcpy(&ss->matrix_stereo[g][sfb], m, sizeof(m));
+ }
+
+ max_sfb_prev = max_sfb_g;
+ }
+
+ for (int k = 0; k < s->frame_len_base; k++) {
+ int sfb = ssch0->offset2sfb[k];
+ int g = ssch0->offset2g[k];
+ float a = ss->matrix_stereo[g][sfb][0][0];
+ float b = ss->matrix_stereo[g][sfb][0][1];
+ float c = ss->matrix_stereo[g][sfb][1][0];
+ float d = ss->matrix_stereo[g][sfb][1][1];
+ float i0 = ssch0->scaled_spec[k];
+ float i1 = ssch1->scaled_spec[k];
+ float o0, o1;
+
+ o0 = i0 * a + i1 * b;
+ o1 = i0 * c + i1 * d;
+
+ ssch0->scaled_spec[k] = o0;
+ ssch1->scaled_spec[k] = o1;
+ }
+
+ return 0;
+}
+
+static int stereo_processing(AC4DecodeContext *s, Substream *ss)
+{
+ if (ss->mdct_stereo_proc[0])
+ two_channel_processing(s, ss, &ss->ssch[0], &ss->ssch[1]);
+
+ return 0;
+}
+
+static int m5channel_processing(AC4DecodeContext *s, Substream *ss)
+{
+ switch (ss->codec_mode) {
+ case CM_SIMPLE:
+ case CM_ASPX:
+ switch (ss->coding_config) {
+ case 0:
+ if (ss->mdct_stereo_proc[0])
+ two_channel_processing(s, ss, &ss->ssch[0], &ss->ssch[1]);
+ if (ss->mdct_stereo_proc[1])
+ two_channel_processing(s, ss, &ss->ssch[2], &ss->ssch[3]);
+ break;
+ }
+ break;
+ case CM_ASPX_ACPL_1:
+ case CM_ASPX_ACPL_2:
+ switch (ss->coding_config) {
+ case 0:
+ if (ss->mdct_stereo_proc[0])
+ two_channel_processing(s, ss, &ss->ssch[0], &ss->ssch[1]);
+ break;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+static void qmf_analysis(AC4DecodeContext *s, SubstreamChannel *ssch)
+{
+ float *qmf_filt = ssch->qmf_filt;
+ float *pcm = ssch->pcm;
+ LOCAL_ALIGNED_32(float, u, [128]);
+ LOCAL_ALIGNED_32(float, z, [640]);
+
+ for (int ts = 0; ts < s->num_qmf_timeslots; ts++) {
+ /* shift time-domain input samples by 64 */
+ memmove(qmf_filt + 64, qmf_filt, sizeof(*qmf_filt) * (640 - 64));
+
+ /* feed new audio samples */
+ for (int sb = 63; sb >= 0; sb--)
+ qmf_filt[sb] = pcm[ts * 64 + 63 - sb];
+
+ /* multiply input samples by window coefficients */
+ s->fdsp->vector_fmul(z, qmf_filt, qwin, 640);
+
+ /* sum the samples to create vector u */
+ for (int n = 0; n < 128; n++) {
+ u[n] = z[n];
+ for (int k = 1; k < 5; k++)
+ u[n] += z[n + k * 128];
+ }
+
+ /* compute 64 new subband samples */
+ for (int sb = 0; sb < 64; sb++) {
+ float *cos_atab = s->cos_atab[sb];
+ float *sin_atab = s->sin_atab[sb];
+
+ ssch->Q[0][ts][sb] = s->fdsp->scalarproduct_float(u, cos_atab, 128);
+ ssch->Q[1][ts][sb] = s->fdsp->scalarproduct_float(u, sin_atab, 128);
+ }
+ }
+}
+
+static void qmf_synthesis(AC4DecodeContext *s, SubstreamChannel *ssch, float *pcm)
+{
+ float *qsyn_filt = ssch->qsyn_filt;
+ LOCAL_ALIGNED_32(float, g, [640]);
+ LOCAL_ALIGNED_32(float, w, [640]);
+
+ for (int ts = 0; ts < s->num_qmf_timeslots; ts++) {
+ /* shift samples by 128 */
+ memmove(qsyn_filt + 128, qsyn_filt, sizeof(*qsyn_filt) * (1280 - 128));
+
+ for (int n = 0; n < 128; n++) {
+ float *cos_stab = s->cos_stab[n];
+ float *sin_stab = s->sin_stab[n];
+
+ qsyn_filt[n] = s->fdsp->scalarproduct_float(ssch->Q[0][ts], cos_stab, 64) -
+ s->fdsp->scalarproduct_float(ssch->Q[1][ts], sin_stab, 64);
+ }
+
+ for (int n = 0; n < 5; n++) {
+ for (int sb = 0; sb < 64; sb++) {
+ g[128*n + sb] = qsyn_filt[256*n + sb];
+ g[128*n + 64 + sb] = qsyn_filt[256*n + 192 + sb];
+ }
+ }
+ /* multiply by window coefficients */
+ s->fdsp->vector_fmul(w, g, qwin, 640);
+
+ /* compute 64 new time-domain output samples */
+ for (int sb = 0; sb < 64; sb++) {
+ float temp = 0;
+
+ for (int n = 0; n < 10; n++)
+ temp += w[64*n + sb];
+ pcm[ts*64 + sb] = temp;
+ }
+ }
+}
+
+static void spectral_synthesis(AC4DecodeContext *s, SubstreamChannel *ssch)
+{
+ LOCAL_ALIGNED_32(float, in, [2048]);
+ LOCAL_ALIGNED_32(float, x, [4096]);
+ const int *win_offset = ssch->win_offset;
+ float *overlap = ssch->overlap;
+ float *winl = s->winl;
+ float *winr = s->winr;
+ float *pcm = ssch->pcm;
+ int Nfull = s->frame_len_base;
+ int nskip, nskip_prev;
+ int win = 0;
+
+ for (int g = 0; g < ssch->scp.num_window_groups; g++) {
+ int midx = s->frame_len_base_idx;
+ int idx;
+ int N = get_transf_length(s, ssch, g, &idx);
+
+ if (!ssch->N_prev)
+ ssch->N_prev = Nfull;
+
+ compute_window(s, winl, N, ssch->N_prev, Nfull, 0);
+ compute_window(s, winr, ssch->N_prev, N, Nfull, 1);
+
+ for (int w = 0; w < ssch->scp.num_win_in_group[g]; w++) {
+ nskip = (Nfull - N) / 2;
+ nskip_prev = (Nfull - ssch->N_prev) / 2;
+
+ memcpy(in, ssch->spec_reord + win_offset[win + w], N * 4);
+
+#if 0
+ s->tx_fn[midx][idx](s->tx_ctx[midx][idx], x, in, sizeof(float));
+
+ s->fdsp->vector_fmul_window(pcm + win_offset[win + w], overlap + nskip, x,
+ s->kbd_window[midx][idx], N >> 1);
+ memcpy(overlap + nskip, x + (N >> 1), sizeof(float)*N >> 1);
+#else
+ s->tx_fn[midx][idx](s->tx_ctx[midx][idx], x + (N >> 1), in, sizeof(float));
+
+ for (int n = 0; n < N >> 1; n++) {
+ x[n] = -x[N-n-1];
+ x[N*2-n-1] = x[N+n];
+ }
+
+ for (int n = 0; n < N / 4; n++) {
+ x[2*n ] *= winl[2*n ];
+ x[2*n+1] *= winl[2*n+1];
+ x[N/2+2*n ] *= winl[N/2+2*n ];
+ x[N/2+2*n+1] *= winl[N/2+2*n+1];
+ }
+
+ /* window second half of previous block */
+ for (int n = 0; n < ssch->N_prev; n++)
+ overlap[nskip_prev + n] *= winr[n];
+
+ /* overlap/add using first N samples from x[n] */
+ for (int n = 0; n < N; n++)
+ overlap[nskip + n] += x[n];
+
+ /* output pcm */
+ for (int n = 0; n < N; n++)
+ pcm[win_offset[win + w] + n] = overlap[n];
+ /* move samples in overlap[] not stored in pcm[] */
+ for (int n = 0; n < nskip; n++)
+ overlap[n] = overlap[N+n];
+
+ /* store second N samples from x[n] for next overlap/add */
+ for (int n = 0; n < N; n++)
+ overlap[nskip + n] = x[N+n];
+#endif
+ }
+
+ ssch->N_prev = N;
+
+ win += ssch->scp.num_win_in_group[g];
+ }
+}
+
+static int polyfit(int order,
+ int countOfElements,
+ const float *const dependentValues,
+ const float *const independentValues,
+ float *coefficients)
+{
+ enum {maxOrder = 5};
+ float B[maxOrder+1] = {0.0f};
+ float P[((maxOrder+1) * 2)+1] = {0.0f};
+ float A[(maxOrder + 1)*2*(maxOrder + 1)] = {0.0f};
+ float x, y, powx;
+ int ii, jj, kk;
+
+ // This method requires that the countOfElements >
+ // (order+1)
+ if (countOfElements <= order)
+ return -1;
+
+ // This method has imposed an arbitrary bound of
+ // order <= maxOrder. Increase maxOrder if necessary.
+ if (order > maxOrder)
+ return -1;
+
+ // Identify the column vector
+ for (ii = 0; ii < countOfElements; ii++) {
+ x = dependentValues[ii];
+ y = independentValues[ii];
+ powx = 1;
+
+ for (jj = 0; jj < (order + 1); jj++) {
+ B[jj] = B[jj] + (y * powx);
+ powx = powx * x;
+ }
+ }
+
+ // Initialize the PowX array
+ P[0] = countOfElements;
+ // Compute the sum of the Powers of X
+ for (ii = 0; ii < countOfElements; ii++) {
+ x = dependentValues[ii];
+ powx = dependentValues[ii];
+
+ for (jj = 1; jj < (2 * (order + 1)) + 1; jj++) {
+ P[jj] = P[jj] + powx;
+ powx = powx * x;
+ }
+ }
+
+ // Initialize the reduction matrix
+ //
+ for (ii = 0; ii < (order + 1); ii++) {
+ for (jj = 0; jj < (order + 1); jj++) {
+ A[(ii * (2 * (order + 1))) + jj] = P[ii+jj];
+ }
+ A[(ii*(2 * (order + 1))) + (ii + (order + 1))] = 1;
+ }
+
+ // Move the Identity matrix portion of the redux matrix
+ // to the left side (find the inverse of the left side
+ // of the redux matrix
+ for (ii = 0; ii < (order + 1); ii++) {
+ x = A[(ii * (2 * (order + 1))) + ii];
+ if (x != 0) {
+ for (kk = 0; kk < (2 * (order + 1)); kk++) {
+ A[(ii * (2 * (order + 1))) + kk] =
+ A[(ii * (2 * (order + 1))) + kk] / x;
+ }
+
+ for (jj = 0; jj < (order + 1); jj++) {
+ if ((jj - ii) != 0) {
+ y = A[(jj * (2 * (order + 1))) + ii];
+ for (kk = 0; kk < (2 * (order + 1)); kk++) {
+ A[(jj * (2 * (order + 1))) + kk] =
+ A[(jj * (2 * (order + 1))) + kk] -
+ y * A[(ii * (2 * (order + 1))) + kk];
+ }
+ }
+ }
+ } else { // Cannot work with singular matrices
+ return -1;
+ }
+ }
+
+ // Calculate and Identify the coefficients
+ for (ii = 0; ii < order + 1; ii++) {
+ for (jj = 0; jj < order + 1; jj++) {
+ x = 0;
+ for (kk = 0; kk < (order + 1); kk++) {
+ x = x + (A[(ii * (2 * (order + 1))) + (kk + (order + 1))] *
+ B[kk]);
+ }
+ coefficients[ii] = x;
+ }
+ }
+
+ return 0;
+}
+
+static int get_qsignal_scale_factors(AC4DecodeContext *s, SubstreamChannel *ssch, int ch)
+{
+ int sbg_idx_high2low[24] = { 0 };
+ int sbg_idx_low2high[24] = { 0 };
+ int sbg_low = 0;
+ int delta;
+
+ for (int sbg = 0; sbg < ssch->num_sbg_sig_highres; sbg++) {
+ if (ssch->sbg_sig_lowres[sbg_low+1] == ssch->sbg_sig_highres[sbg]) {
+ sbg_low++;
+ sbg_idx_low2high[sbg_low] = sbg;
+ }
+ sbg_idx_high2low[sbg] = sbg_low;
+ }
+
+ delta = ((ch == 1) && (ssch->aspx_balance == 1)) + 1;
+
+ memcpy(ssch->qscf_sig_sbg_prev, ssch->qscf_sig_sbg, sizeof(ssch->qscf_sig_sbg));
+
+ /* Loop over Envelopes */
+ for (int atsg = 0; atsg < ssch->aspx_num_env; atsg++) {
+ /* Loop over scale factor subband groups */
+ for (int sbg = 0; sbg < ssch->num_sbg_sig[atsg]; sbg++) {
+ if (atsg == 0) {
+ ssch->atsg_freqres_prev[atsg] = ssch->atsg_freqres[ssch->aspx_num_env_prev - 1];
+ ssch->qscf_prev[sbg][atsg] = ssch->qscf_sig_sbg_prev[sbg][ssch->aspx_num_env_prev - 1];
+ } else {
+ ssch->atsg_freqres_prev[atsg] = ssch->atsg_freqres[atsg-1];
+ ssch->qscf_prev[sbg][atsg] = ssch->qscf_sig_sbg[sbg][atsg-1];
+ }
+ if (ssch->aspx_sig_delta_dir[atsg] == 0) { /* FREQ */
+ ssch->qscf_sig_sbg[sbg][atsg] = 0;
+ for (int i = 0; i <= sbg; i++) {
+ ssch->qscf_sig_sbg[sbg][atsg] += delta * ssch->aspx_data[0][atsg][i];
+ }
+ } else { /* TIME */
+ if (ssch->atsg_freqres[atsg] == ssch->atsg_freqres_prev[atsg]) {
+ ssch->qscf_sig_sbg[sbg][atsg] = ssch->qscf_prev[sbg][atsg];
+ ssch->qscf_sig_sbg[sbg][atsg] += delta * ssch->aspx_data[0][atsg][sbg];
+ } else if ((ssch->atsg_freqres[atsg] == 0) && (ssch->atsg_freqres_prev[atsg] == 1)) {
+ ssch->qscf_sig_sbg[sbg][atsg] = ssch->qscf_prev[sbg_idx_low2high[sbg]][atsg];
+ ssch->qscf_sig_sbg[sbg][atsg] += delta * ssch->aspx_data[0][atsg][sbg];
+ } else if ((ssch->atsg_freqres[atsg] == 1) && (ssch->atsg_freqres_prev[atsg] == 0)) {
+ ssch->qscf_sig_sbg[sbg][atsg] = ssch->qscf_prev[sbg_idx_high2low[sbg]][atsg];
+ ssch->qscf_sig_sbg[sbg][atsg] += delta * ssch->aspx_data[0][atsg][sbg];
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int get_qnoise_scale_factors(AC4DecodeContext *s, SubstreamChannel *ssch, int ch)
+{
+ int delta;
+
+ if ((ch == 1) && (ssch->aspx_balance == 1)) {
+ delta = 2;
+ } else {
+ delta = 1;
+ }
+
+ /* Loop over envelopes */
+ for (int atsg = 0; atsg < ssch->aspx_num_noise; atsg++) {
+ /* Loop over noise subband groups */
+ for (int sbg = 0; sbg < ssch->num_sbg_noise; sbg++) {
+ ssch->qscf_noise_sbg[sbg][atsg] = 0;
+ if (ssch->aspx_noise_delta_dir[atsg] == 0) { /* FREQ */
+ for (int i = 0; i <= sbg; i++) {
+ ssch->qscf_noise_sbg[sbg][atsg] += delta * ssch->aspx_data[1][atsg][sbg];
+ }
+ } else { /* TIME */
+ if (atsg == 0) {
+ ssch->qscf_noise_sbg[sbg][atsg] = ssch->qscf_prev[sbg][ssch->aspx_num_noise_prev-1];
+ ssch->qscf_noise_sbg[sbg][atsg] += delta * ssch->aspx_data[1][atsg][sbg];
+ } else {
+ ssch->qscf_noise_sbg[sbg][atsg] = ssch->qscf_noise_sbg[sbg][atsg-1];
+ ssch->qscf_noise_sbg[sbg][atsg] += delta * ssch->aspx_data[1][atsg][sbg];
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+static void prepare_channel(AC4DecodeContext *s, int ch)
+{
+ Substream *ss = &s->substream;
+ SubstreamChannel *ssch = &ss->ssch[ch];
+
+ spectral_reordering(s, ssch);
+ spectral_synthesis(s, ssch);
+
+ qmf_analysis(s, ssch);
+}
+
+static void aspx_processing(AC4DecodeContext *s, SubstreamChannel *ssch)
+{
+ memcpy(ssch->Q_low_prev, ssch->Q_low, sizeof(ssch->Q_low));
+
+ for (int ts = 0; ts < s->ts_offset_hfgen; ts++) {
+ for (int sb = 0; sb < 64; sb++) {
+ if (sb < ssch->sbx) {
+ ssch->Q_low[0][ts][sb] = ssch->Q_prev[0][ts + s->num_qmf_timeslots - s->ts_offset_hfgen][sb];
+ ssch->Q_low[1][ts][sb] = ssch->Q_prev[1][ts + s->num_qmf_timeslots - s->ts_offset_hfgen][sb];
+ }
+ }
+ }
+
+ for (int ts = s->ts_offset_hfgen; ts < s->num_qmf_timeslots + s->ts_offset_hfgen; ts++) {
+ for (int sb = 0; sb < 64; sb++) {
+ if (sb < ssch->sbx) {
+ ssch->Q_low[0][ts][sb] = ssch->Q[0][ts - s->ts_offset_hfgen][sb];
+ ssch->Q_low[1][ts][sb] = ssch->Q[1][ts - s->ts_offset_hfgen][sb];
+ }
+ }
+ }
+}
+
+static void mono_deq_signal_factors(AC4DecodeContext *s, SubstreamChannel *ssch)
+{
+ float a = (ssch->aspx_qmode_env == 0) + 1;
+
+ for (int atsg = 0; atsg < ssch->aspx_num_env; atsg++) {
+ for (int sbg = 0; sbg < ssch->num_sbg_sig[atsg]; sbg++)
+ ssch->scf_sig_sbg[sbg][atsg] = powf(2, ssch->qscf_sig_sbg[sbg][atsg] / a) / 512.f;
+
+ if (ssch->aspx_sig_delta_dir[atsg] == 0 &&
+ ssch->qscf_sig_sbg[0][atsg] == 0 &&
+ ssch->scf_sig_sbg[1][atsg] < 0) {
+ ssch->scf_sig_sbg[0][atsg] = ssch->scf_sig_sbg[1][atsg];
+ }
+ }
+}
+
+static void mono_deq_noise_factors(AC4DecodeContext *s, SubstreamChannel *ssch)
+{
+#define NOISE_FLOOR_OFFSET 6
+
+ for (int atsg = 0; atsg < ssch->aspx_num_noise; atsg++) {
+ for (int sbg = 0; sbg < ssch->num_sbg_noise; sbg++)
+ ssch->scf_noise_sbg[sbg][atsg] = powf(2, NOISE_FLOOR_OFFSET - ssch->qscf_noise_sbg[sbg][atsg]);
+ }
+}
+
+static void stereo_deq_signoise_factors(AC4DecodeContext *s,
+ SubstreamChannel *ssch0,
+ SubstreamChannel *ssch1)
+{
+#define PAN_OFFSET 12
+
+ float a = 1 + (ssch0->aspx_qmode_env == 0);
+
+ for (int atsg = 0; atsg < ssch0->aspx_num_env; atsg++) {
+ for (int sbg = 0; sbg < ssch0->num_sbg_sig[atsg]; sbg++) {
+ float nom = powf(2, ssch0->qscf_sig_sbg[sbg][atsg] / a + 1) / 512.f;
+ float denom_a = 1 + powf(2, PAN_OFFSET - ssch1->qscf_sig_sbg[sbg][atsg] / a);
+ float denom_b = 1 + powf(2, ssch1->qscf_sig_sbg[sbg][atsg] / a - PAN_OFFSET);
+
+ ssch0->scf_sig_sbg[sbg][atsg] = nom / denom_a;
+ ssch1->scf_sig_sbg[sbg][atsg] = nom / denom_b;
+ }
+ }
+
+ for (int atsg = 0; atsg < ssch0->aspx_num_noise; atsg++) {
+ for (int sbg = 0; sbg < ssch0->num_sbg_noise; sbg++) {
+ float nom = powf(2, NOISE_FLOOR_OFFSET - ssch0->qscf_noise_sbg[sbg][atsg] + 1);
+ float denom_a = 1 + powf(2, PAN_OFFSET - ssch1->qscf_noise_sbg[sbg][atsg]);
+ float denom_b = 1 + powf(2, ssch1->qscf_noise_sbg[sbg][atsg] - PAN_OFFSET);
+
+ ssch0->scf_noise_sbg[sbg][atsg] = nom / denom_a;
+ ssch1->scf_noise_sbg[sbg][atsg] = nom / denom_b;
+ }
+ }
+}
+
+static void preflattening(AC4DecodeContext *s, SubstreamChannel *ssch)
+{
+ float mean_energy = 0;
+ int polynomial_order = 3;
+ int num_qmf_subbands = ssch->sbx;
+ float x[32]; // XXX
+ float slope[32]; // XXX
+ float pow_env[32]; // XXX
+ float poly_array[32]; // XXX
+
+ for (int i = 0; i < num_qmf_subbands; i++) {
+ x[i] = i;
+ slope[i] = 0;
+ }
+ /* Calculate the spectral signal envelope in dB over the current interval. */
+ for (int sb = 0; sb < num_qmf_subbands; sb++) {
+ pow_env[sb] = 0;
+ for (int ts = ssch->atsg_sig[0] * s->num_ts_in_ats; ts < ssch->atsg_sig[ssch->aspx_num_env] * s->num_ts_in_ats; ts++) {
+ pow_env[sb] += powf(ssch->Q_low[0][ts][sb], 2);
+ pow_env[sb] += powf(ssch->Q_low[1][ts][sb], 2);
+ }
+ pow_env[sb] /= (ssch->atsg_sig[ssch->aspx_num_env] - ssch->atsg_sig[0]) * s->num_ts_in_ats;
+ pow_env[sb] = 10 * log10f(pow_env[sb] + 1);
+ mean_energy += pow_env[sb];
+ }
+
+ mean_energy /= num_qmf_subbands;
+ polyfit(polynomial_order, num_qmf_subbands, x, pow_env, poly_array);
+
+ /* Transform polynomial into slope */
+ for (int k = polynomial_order; k >= 0; k--) {
+ for (int sb = 0; sb < num_qmf_subbands; sb++)
+ slope[sb] += powf(x[sb], k) * poly_array[k];
+ }
+
+ /* Derive a gain vector from the slope */
+ for (int sb = 0; sb < num_qmf_subbands; sb++) {
+ ssch->gain_vec[sb] = powf(10, (mean_energy - slope[sb]) / 20.f);
+ }
+}
+
+static void get_chirps(AC4DecodeContext *s, SubstreamChannel *ssch)
+{
+ memcpy(ssch->chirp_arr_prev, ssch->chirp_arr, sizeof(ssch->chirp_arr));
+
+ for (int sbg = 0; sbg < ssch->num_sbg_noise; sbg++) {
+ float new_chirp = new_chirp_tab[ssch->aspx_tna_mode[sbg]][ssch->aspx_tna_mode_prev[sbg]];
+
+ if (new_chirp < ssch->chirp_arr_prev[sbg]) {
+ new_chirp = 0.75000f * new_chirp + 0.25000f * ssch->chirp_arr_prev[sbg];
+ } else {
+ new_chirp = 0.90625f * new_chirp + 0.09375f * ssch->chirp_arr_prev[sbg];
+ }
+
+ if (new_chirp < 0.015625f) {
+ ssch->chirp_arr[sbg] = 0.f;
+ } else {
+ ssch->chirp_arr[sbg] = new_chirp;
+ }
+ }
+}
+
+static void get_covariance(AC4DecodeContext *s, SubstreamChannel *ssch)
+{
+ int num_ts_ext;
+ int ts_offset_hfadj = 4;
+
+ /* Create an additional delay of ts_offset_hfadj QMF time slots */
+ for (int sb = 0; sb < ssch->sba; sb++) {
+ int ts_offset_prev = s->num_qmf_timeslots - ts_offset_hfadj;
+
+ for (int ts = 0; ts < ts_offset_hfadj; ts++) {
+ ssch->Q_low_ext[0][ts][sb] = ssch->Q_low_prev[0][ts + ts_offset_prev][sb];
+ ssch->Q_low_ext[1][ts][sb] = ssch->Q_low_prev[1][ts + ts_offset_prev][sb];
+ }
+
+ for (int ts = 0; ts < s->num_qmf_timeslots + s->ts_offset_hfgen; ts++) {
+ ssch->Q_low_ext[0][ts + ts_offset_hfadj][sb] = ssch->Q_low[0][ts][sb];
+ ssch->Q_low_ext[1][ts + ts_offset_hfadj][sb] = ssch->Q_low[1][ts][sb];
+ }
+ }
+
+ num_ts_ext = s->num_qmf_timeslots + s->ts_offset_hfgen + ts_offset_hfadj;
+ /* Loop over QMF subbands */
+ for (int sb = 0; sb < ssch->sba; sb++) {
+ for (int i = 0; i < 3; i++) {
+ for (int j = 1; j < 3; j++) {
+ ssch->cov[sb][i][j][0] = 0;
+ ssch->cov[sb][i][j][1] = 0;
+ /* Loop over QMF time slots */
+ for (int ts = ts_offset_hfadj; ts < num_ts_ext; ts += 2) {
+ ssch->cov[sb][i][j][0] += ssch->Q_low_ext[0][ts - 2*i][sb] * ssch->Q_low_ext[0][ts - 2*j][sb];
+ ssch->cov[sb][i][j][0] += ssch->Q_low_ext[1][ts - 2*i][sb] * ssch->Q_low_ext[1][ts - 2*j][sb];
+ ssch->cov[sb][i][j][1] -= ssch->Q_low_ext[0][ts - 2*i][sb] * ssch->Q_low_ext[1][ts - 2*j][sb];
+ ssch->cov[sb][i][j][1] += ssch->Q_low_ext[1][ts - 2*i][sb] * ssch->Q_low_ext[0][ts - 2*j][sb];
+ }
+ }
+ }
+ }
+}
+
+static void complex_div(float *r, float *i, float x, float yi, float u, float vi)
+{
+ *r = (x*u + yi*vi) / (u * u + vi * vi);
+ *i = (x*vi - u*yi) / (u * u + vi * vi);
+}
+
+static void complex_mul(float *r, float *i, float x, float yi, float u, float vi)
+{
+ *r = x*u - yi*vi;
+ *i = x*vi + u*yi;
+}
+
+static void get_alphas(AC4DecodeContext *s, SubstreamChannel *ssch)
+{
+ float EPSILON_INV = powf(2,-20);
+
+ for (int sb = 0; sb < ssch->sba; sb++) {
+ float denom[2];
+
+ complex_mul(&denom[0], &denom[1], ssch->cov[sb][2][2][0], ssch->cov[sb][2][2][1], ssch->cov[sb][1][1][0], ssch->cov[sb][1][1][1]);
+ denom[0] -= (ssch->cov[sb][1][2][0] * ssch->cov[sb][1][2][0] + ssch->cov[sb][1][2][1] * ssch->cov[sb][1][2][1]) * 1/(1+EPSILON_INV);
+ if (denom[0] == 0 && denom[1] == 0) {
+ ssch->alpha1[sb][0] = 0;
+ ssch->alpha1[sb][1] = 0;
+ } else {
+ ssch->alpha1[sb][0] = (ssch->cov[sb][0][1][0] * ssch->cov[sb][1][2][0] - ssch->cov[sb][0][1][1] * ssch->cov[sb][1][2][1]) -
+ (ssch->cov[sb][0][2][0] * ssch->cov[sb][1][1][0] - ssch->cov[sb][0][2][1] * ssch->cov[sb][1][1][1]);
+ ssch->alpha1[sb][1] = (ssch->cov[sb][0][1][0] * ssch->cov[sb][1][2][1] + ssch->cov[sb][0][1][1] * ssch->cov[sb][1][2][0]) -
+ (ssch->cov[sb][0][2][0] * ssch->cov[sb][1][1][1] + ssch->cov[sb][0][2][1] * ssch->cov[sb][1][1][0]);
+ complex_div(&ssch->alpha1[sb][0], &ssch->alpha1[sb][1], ssch->alpha1[sb][0], ssch->alpha1[sb][1], denom[0], denom[1]);
+ }
+
+ if (ssch->cov[sb][1][1][0] == 0 &&
+ ssch->cov[sb][1][1][1] == 0) {
+ ssch->alpha0[sb][0] = 0;
+ ssch->alpha0[sb][1] = 0;
+ } else {
+ ssch->alpha0[sb][0] = -ssch->cov[sb][0][1][0] + ssch->alpha1[sb][0] * ssch->cov[sb][1][2][0] + ssch->alpha1[sb][1] * ssch->cov[sb][1][2][1];
+ ssch->alpha0[sb][1] = -ssch->cov[sb][0][1][1] + ssch->alpha1[sb][1] * ssch->cov[sb][1][2][0] - ssch->alpha1[sb][0] * ssch->cov[sb][1][2][1];
+ complex_div(&ssch->alpha0[sb][0], &ssch->alpha0[sb][1], ssch->alpha0[sb][0], ssch->alpha0[sb][1], ssch->cov[sb][1][1][0], ssch->cov[sb][1][1][1]);
+ }
+
+ if (hypotf(ssch->alpha0[sb][0], ssch->alpha0[sb][1]) >= 4.f ||
+ hypotf(ssch->alpha1[sb][0], ssch->alpha1[sb][1]) >= 4.f) {
+ ssch->alpha0[sb][0] = ssch->alpha0[sb][1] = 0;
+ ssch->alpha1[sb][0] = ssch->alpha1[sb][1] = 0;
+ }
+ }
+}
+
+static void create_high_signal(AC4DecodeContext *s, Substream *ss, SubstreamChannel *ssch)
+{
+ int ts_offset_hfadj = 4;
+
+ /* Loop over QMF time slots */
+ for (int ts = ssch->atsg_sig[0]*s->num_ts_in_ats; ts < ssch->atsg_sig[ssch->aspx_num_env] * s->num_ts_in_ats; ts++) {
+ int sum_sb_patches = 0;
+ int g = 0;
+ /* Loop over number of patches */
+ for (int i = 0; i < ssch->num_sbg_patches; i++) {
+ /* Loop over number of subbands per patch */
+ for (int sb = 0; sb < ssch->sbg_patch_num_sb[i]; sb++) {
+ float cplx[2] = { 0 };
+ /* Map to High QMF Subband */
+ int n, p;
+ int sb_high = ssch->sbx + sum_sb_patches + sb;
+
+ /* Map to current noise envelope */
+ if (ssch->sbg_noise[g+1] == sb_high)
+ g++;
+
+ n = ts + ts_offset_hfadj;
+ /* Current low QMF Subband */
+ p = ssch->sbg_patch_start_sb[i] + sb;
+ ssch->Q_high[0][ts][sb_high] = ssch->Q_low_ext[0][n][p];
+ ssch->Q_high[1][ts][sb_high] = ssch->Q_low_ext[1][n][p];
+
+ complex_mul(&cplx[0], &cplx[1], ssch->alpha0[p][0], ssch->alpha0[p][1], ssch->Q_low_ext[0][n-2][p], ssch->Q_low_ext[1][n-2][p]);
+ complex_mul(&cplx[0], &cplx[1], cplx[0], cplx[1], ssch->chirp_arr[g], 0);
+ ssch->Q_high[0][ts][sb_high] += cplx[0];
+ ssch->Q_high[1][ts][sb_high] += cplx[1];
+ complex_mul(&cplx[0], &cplx[1], ssch->alpha1[p][0], ssch->alpha1[p][1], ssch->Q_low_ext[0][n-4][p], ssch->Q_low_ext[1][n-4][p]);
+ complex_mul(&cplx[0], &cplx[1], cplx[0], cplx[1], powf(ssch->chirp_arr[g], 2), 0);
+ ssch->Q_high[0][ts][sb_high] += cplx[0];
+ ssch->Q_high[1][ts][sb_high] += cplx[1];
+ if (ss->aspx_preflat == 1)
+ complex_mul(&ssch->Q_high[0][ts][sb_high], &ssch->Q_high[1][ts][sb_high], ssch->Q_high[0][ts][sb_high], ssch->Q_high[1][ts][sb_high], 1.f / ssch->gain_vec[p], 0);
+ }
+ sum_sb_patches += ssch->sbg_patch_num_sb[i];
+ }
+ }
+}
+
+static void estimate_spectral_envelopes(AC4DecodeContext *s, Substream *ss, SubstreamChannel *ssch)
+{
+ int ts_offset_hfadj = 4;
+
+ for (int atsg = 0; atsg < ssch->aspx_num_env; atsg++) {
+ int sbg = 0;
+ /* Loop over QMF subbands in A-SPX range */
+ for (int sb = 0; sb < ssch->num_sb_aspx; sb++) {
+ int tsa, tsz;
+ float est_sig = 0;
+
+ /* Update current subband group */
+ if (sb == ssch->sbg_sig[atsg][sbg+1])
+ sbg++;
+
+ tsa = ssch->atsg_sig[atsg]*s->num_ts_in_ats + ts_offset_hfadj;
+ tsz = ssch->atsg_sig[atsg+1]*s->num_ts_in_ats + ts_offset_hfadj;
+ for (int ts = tsa; ts < tsz; ts++) {
+ if (ss->aspx_interpolation == 0) {
+ for (int j = ssch->sbg_sig[atsg][sbg]; j < ssch->sbg_sig[atsg][sbg+1]; j++) {
+ est_sig += powf(ssch->Q_high[0][ts][j], 2) +
+ powf(ssch->Q_high[1][ts][j], 2);
+ }
+ } else {
+ est_sig += powf(ssch->Q_high[0][ts][sb+ssch->sbx], 2) +
+ powf(ssch->Q_high[1][ts][sb+ssch->sbx], 2);
+ }
+ }
+
+ if (ss->aspx_interpolation == 0) {
+ est_sig /= ssch->sbg_sig[atsg][sbg+1] - ssch->sbg_sig[atsg][sbg];
+ est_sig /= ssch->atsg_sig[atsg+1] - ssch->atsg_sig[atsg];
+ } else {
+ est_sig /= ssch->atsg_sig[atsg+1] - ssch->atsg_sig[atsg];
+ }
+ ssch->est_sig_sb[sb][atsg] = est_sig;
+ }
+ }
+}
+
+static void map_signoise(AC4DecodeContext *s, SubstreamChannel *ssch)
+{
+ int atsg_noise = 0;
+
+ /* Loop over Signal Envelopes */
+ for (int atsg = 0; atsg < ssch->aspx_num_env; atsg++) {
+ /* Map Signal Envelopes from subband groups to QMF subbands */
+
+ for (int sbg = 0; sbg < ssch->num_sbg_sig[atsg]; sbg++) {
+ for (int sb = ssch->sbg_sig[atsg][sbg]-ssch->sbx; sb < ssch->sbg_sig[atsg][sbg+1]-ssch->sbx; sb++)
+ ssch->scf_sig_sb[sb][atsg] = ssch->scf_sig_sbg[sbg][atsg];
+
+ }
+
+ if (ssch->atsg_sig[atsg] == ssch->atsg_noise[atsg_noise + 1])
+ atsg_noise++;
+
+ /* Map Noise Floors from subband groups to QMF subbands, and to signal envelopes */
+ for (int sbg = 0; sbg < ssch->num_sbg_noise; sbg++) {
+ for (int sb = ssch->sbg_noise[sbg]-ssch->sbx; sb < ssch->sbg_noise[sbg+1]-ssch->sbx; sb++)
+ ssch->scf_noise_sb[sb][atsg] = ssch->scf_noise_sbg[sbg][atsg_noise];
+ }
+ }
+}
+
+static void add_sinusoids(AC4DecodeContext *s, SubstreamChannel *ssch)
+{
+ int p_sine_at_end;
+
+ if (ssch->aspx_tsg_ptr_prev == ssch->aspx_num_env_prev)
+ p_sine_at_end = 0;
+ else
+ p_sine_at_end = -1;
+
+ memcpy(ssch->sine_idx_sb_prev, ssch->sine_idx_sb, sizeof(ssch->sine_idx_sb));
+
+ /* Loop over envelopes */
+ for (int atsg = 0; atsg < ssch->aspx_num_env; atsg++) {
+ /* Loop over high resolution signal envelope subband groups */
+ for (int sbg = 0; sbg < ssch->num_sbg_sig_highres; sbg++) {
+ int sba = ssch->sbg_sig_highres[sbg] - ssch->sbx;
+ int sbz = ssch->sbg_sig_highres[sbg+1] - ssch->sbx;
+ int sb_mid = (int)0.5*(sbz+sba);
+ /* Map sinusoid markers to QMF subbands */
+ for (int sb = ssch->sbg_sig_highres[sbg]-ssch->sbx; sb < ssch->sbg_sig_highres[sbg+1]-ssch->sbx; sb++) {
+ if ((sb == sb_mid) && ((atsg >= ssch->aspx_tsg_ptr) || (p_sine_at_end == 0)
+ || ssch->sine_idx_sb_prev[sb][ssch->aspx_num_env_prev-1])) {
+ ssch->sine_idx_sb[sb][atsg] = ssch->aspx_add_harmonic[sbg];
+ } else {
+ ssch->sine_idx_sb[sb][atsg] = 0;
+ }
+ }
+ }
+ }
+
+ for (int atsg = 0; atsg < ssch->aspx_num_env; atsg++) {
+ /* Loop over subband groups */
+ for (int sbg = 0; sbg < ssch->num_sbg_sig[atsg]; sbg++) {
+ int sine_present = 0;
+ /* Additional sinusoid present in SF band? */
+ for (int sb = ssch->sbg_sig[atsg][sbg]-ssch->sbx; sb < ssch->sbg_sig[atsg][sbg+1]-ssch->sbx; sb++) {
+ if (ssch->sine_idx_sb[sb][atsg] == 1)
+ sine_present = 1;
+ }
+
+ /* Mark all subbands in current subband group accordingly */
+ for (int sb = ssch->sbg_sig[atsg][sbg]-ssch->sbx; sb < ssch->sbg_sig[atsg][sbg+1]-ssch->sbx; sb++) {
+ ssch->sine_area_sb[sb][atsg] = sine_present;
+ }
+ }
+ }
+
+ /* Loop over envelopes */
+ for (int atsg = 0; atsg < ssch->aspx_num_env; atsg++) {
+ /* Loop over QMF subbands in A-SPX range */
+ for (int sb = 0; sb < ssch->num_sb_aspx; sb++) {
+ float sig_noise_fact = ssch->scf_sig_sb[sb][atsg] / (1+ssch->scf_noise_sb[sb][atsg]);
+
+ ssch->sine_lev_sb[sb][atsg] = sqrtf(sig_noise_fact * ssch->sine_idx_sb[sb][atsg]);
+ ssch->noise_lev_sb[sb][atsg] = sqrtf(sig_noise_fact * ssch->scf_noise_sb[sb][atsg]);
+ }
+ }
+
+ float EPSILON = 1.0;
+
+ /* Loop over envelopes */
+ for (int atsg = 0; atsg < ssch->aspx_num_env; atsg++) {
+ /* Loop over QMF subbands in A-SPX range */
+ for (int sb = 0; sb < ssch->num_sb_aspx; sb++) {
+ if (ssch->sine_area_sb[sb][atsg] == 0) {
+ float denom = EPSILON + ssch->est_sig_sb[sb][atsg];
+ if (!(atsg == ssch->aspx_tsg_ptr || atsg == p_sine_at_end))
+ denom *= (1 + ssch->scf_noise_sb[sb][atsg]);
+ ssch->sig_gain_sb[sb][atsg] = sqrtf(ssch->scf_sig_sb[sb][atsg] / denom);
+ } else {
+ float denom = EPSILON + ssch->est_sig_sb[sb][atsg];
+ denom *= 1 + ssch->scf_noise_sb[sb][atsg];
+ ssch->sig_gain_sb[sb][atsg] = sqrtf(ssch->scf_sig_sb[sb][atsg]*ssch->scf_noise_sb[sb][atsg] / denom);
+ }
+ }
+ }
+
+ float LIM_GAIN = 1.41254;
+ float EPSILON0 = powf(10, -12);
+ float MAX_SIG_GAIN = powf(10, 5);
+
+ /* Loop over envelopes */
+ for (int atsg = 0; atsg < ssch->aspx_num_env; atsg++) {
+ /* Loop over limiter subband groups */
+ for (int sbg = 0; sbg < ssch->num_sbg_lim; sbg++) {
+ float nom = 0;
+ float denom = EPSILON0;
+ for (int sb = ssch->sbg_lim[sbg]-ssch->sbx; sb < ssch->sbg_lim[sbg+1]-1-ssch->sbx; sb++) {
+ nom += ssch->scf_sig_sb[sb][atsg];
+ denom += ssch->est_sig_sb[sb][atsg];
+ }
+
+ ssch->max_sig_gain_sbg[sbg][atsg] = sqrtf(nom/denom) * LIM_GAIN;
+ }
+
+ int sbg = 0;
+ /* Map to QMF subbands */
+ for (int sb = 0; sb < ssch->num_sb_aspx; sb++) {
+ if (sb == ssch->sbg_lim[sbg+1]-ssch->sbx)
+ sbg++;
+ ssch->max_sig_gain_sb[sb][atsg] = FFMIN(ssch->max_sig_gain_sbg[sbg][atsg], MAX_SIG_GAIN);
+ }
+ }
+
+ /* Loop over envelopes */
+ for (int atsg = 0; atsg < ssch->aspx_num_env; atsg++) {
+ /* Loop over QMF subbands */
+ for (int sb = 0; sb < ssch->num_sb_aspx; sb++) {
+ float tmp = ssch->noise_lev_sb[sb][atsg];
+
+ tmp *= ssch->max_sig_gain_sb[sb][atsg] / ssch->sig_gain_sb[sb][atsg];
+ ssch->noise_lev_sb_lim[sb][atsg] = FFMIN(ssch->noise_lev_sb[sb][atsg], tmp);
+ }
+ }
+
+ /* Loop over envelopes */
+ for (int atsg = 0; atsg < ssch->aspx_num_env; atsg++) {
+ /* Loop over QMF subbands */
+ for (int sb = 0; sb < ssch->num_sb_aspx; sb++) {
+ ssch->sig_gain_sb_lim[sb][atsg] = FFMIN(ssch->sig_gain_sb[sb][atsg],
+ ssch->max_sig_gain_sb[sb][atsg]);
+ }
+ }
+
+ /* Loop over envelopes */
+ for (int atsg = 0; atsg < ssch->aspx_num_env; atsg++) {
+ /* Loop over limiter subband groups */
+ for (int sbg = 0; sbg < ssch->num_sbg_lim; sbg++) {
+ float nom, denom;
+
+ nom = denom = EPSILON0;
+ /* Loop over subbands */
+ for (int sb = ssch->sbg_lim[sbg]-ssch->sbx; sb < ssch->sbg_lim[sbg+1]-1-ssch->sbx; sb++) {
+ nom += ssch->scf_sig_sb[sb][atsg];
+ denom += ssch->est_sig_sb[sb][atsg] * powf(ssch->sig_gain_sb_lim[sb][atsg], 2);
+ denom += powf(ssch->sine_lev_sb[sb][atsg], 2);
+ if (!((ssch->sine_lev_sb[sb][atsg] != 0)
+ || (atsg == ssch->aspx_tsg_ptr) || (atsg == p_sine_at_end)))
+ denom += powf(ssch->noise_lev_sb_lim[sb][atsg], 2);
+ }
+ ssch->boost_fact_sbg[sbg][atsg] = sqrtf(nom/denom);
+ }
+ }
+
+ float MAX_BOOST_FACT = 1.584893192;
+ /* Loop over envelopes */
+ for (int atsg = 0; atsg < ssch->aspx_num_env; atsg++) {
+ int sbg = 0;
+ /* Loop over QMF subbands */
+ for (int sb = 0; sb < ssch->num_sb_aspx; sb++) {
+ if (sb == ssch->sbg_lim[sbg+1]-ssch->sbx)
+ sbg++;
+ ssch->boost_fact_sb[sb][atsg] = FFMIN(ssch->boost_fact_sbg[sbg][atsg], MAX_BOOST_FACT);
+ }
+ }
+
+ /* Loop over envelopes */
+ for (int atsg = 0; atsg < ssch->aspx_num_env; atsg++) {
+ /* Loop over QMF subbands */
+ for (int sb = 0; sb < ssch->num_sb_aspx; sb++) {
+ float boost_fact = ssch->boost_fact_sb[sb][atsg];
+ ssch->sig_gain_sb_adj[sb][atsg] = ssch->sig_gain_sb_lim[sb][atsg] * boost_fact;
+ ssch->noise_lev_sb_adj[sb][atsg] = ssch->noise_lev_sb_lim[sb][atsg] * boost_fact;
+ ssch->sine_lev_sb_adj[sb][atsg] = ssch->sine_lev_sb[sb][atsg] * boost_fact;
+ }
+ }
+}
+
+static int sine_idx(int sb, int ts, AC4DecodeContext *s, SubstreamChannel *ssch)
+{
+ int index;
+
+ if (s->have_iframe) {
+ index = 1;
+ } else {
+ index = (ssch->sine_idx_prev[sb][ts] + 1) % 4;
+ }
+ index += ts - ssch->atsg_sig[0];
+
+ return index % 4;
+}
+
+static void generate_tones(AC4DecodeContext *s, SubstreamChannel *ssch)
+{
+ int atsg = 0;
+ /* Loop over QMF time slots */
+ for (int ts = ssch->atsg_sig[0] * s->num_ts_in_ats;
+ ts < ssch->atsg_sig[ssch->aspx_num_env] * s->num_ts_in_ats; ts++) {
+ if (ts == ssch->atsg_sig[atsg+1] * s->num_ts_in_ats)
+ atsg++;
+ /* Loop over QMF subbands in A-SPX */
+ for (int sb = 0; sb < ssch->num_sb_aspx; sb++) {
+ int idx;
+
+ ssch->sine_idx[sb][ts] = idx = sine_idx(sb, ts, s, ssch);
+ ssch->qmf_sine[0][ts][sb] = ssch->sine_lev_sb_adj[sb][atsg];
+ ssch->qmf_sine[0][ts][sb] *= SineTable[0][idx];
+ ssch->qmf_sine[1][ts][sb] = ssch->sine_lev_sb_adj[sb][atsg] * powf(-1, sb + ssch->sbx);
+ ssch->qmf_sine[1][ts][sb] *= SineTable[1][idx];
+ }
+ }
+}
+
+static void assemble_hf_signal(AC4DecodeContext *s, SubstreamChannel *ssch)
+{
+ int ts_offset_hfadj = 4;
+ int atsg = 0;
+ /* Get delayed QMF subsamples from delay buffer */
+ for (int ts = 0; ts < ssch->atsg_sig[0] * s->num_ts_in_ats; ts++) {
+ for (int sb = 0; sb < ssch->num_sb_aspx; sb++) {
+ ssch->Y[0][ts][sb] = ssch->Y_prev[0][s->num_qmf_timeslots + ts][sb];
+ ssch->Y[1][ts][sb] = ssch->Y_prev[1][s->num_qmf_timeslots + ts][sb];
+ }
+ }
+
+ /* Loop over QMF time slots */
+ for (int ts = ssch->atsg_sig[0] * s->num_ts_in_ats;
+ ts < ssch->atsg_sig[ssch->aspx_num_env] * s->num_ts_in_ats; ts++) {
+ if (ts == ssch->atsg_sig[atsg+1] * s->num_ts_in_ats)
+ atsg++;
+ /* Loop over QMF subbands */
+ for (int sb = 0; sb < ssch->num_sb_aspx; sb++) {
+ ssch->Y[0][ts][sb] = ssch->sig_gain_sb_adj[sb][atsg];
+ ssch->Y[1][ts][sb] = 0;
+ complex_mul(&ssch->Y[0][ts][sb], &ssch->Y[1][ts][sb],
+ ssch->Y[0][ts][sb], ssch->Y[1][ts][sb],
+ ssch->Q_high[0][ts + ts_offset_hfadj][sb + ssch->sbx],
+ ssch->Q_high[1][ts + ts_offset_hfadj][sb + ssch->sbx]);
+ }
+ }
+
+ memcpy(ssch->Y_prev, ssch->Y, sizeof(ssch->Y));
+
+ /* Loop over time slots */
+ for (int ts = ssch->atsg_sig[0]; ts < ssch->atsg_sig[ssch->aspx_num_env]; ts++) {
+ /* Loop over QMF subbands */
+ for (int sb = 0; sb < ssch->num_sb_aspx; sb++) {
+ ssch->Y[0][ts][sb] += ssch->qmf_sine[0][ts][sb];
+ ssch->Y[1][ts][sb] += ssch->qmf_sine[1][ts][sb];
+ }
+ }
+
+ memcpy(ssch->Q_prev, ssch->Q, sizeof(ssch->Q));
+
+ for (int ts = 0; ts < s->num_qmf_timeslots; ts++) {
+ /* Loop over QMF subbands */
+ for (int sb = 0; sb < 64; sb++) {
+ ssch->Q[0][ts][sb] += ssch->Y[0][ts+s->ts_offset_hfgen][sb];
+ ssch->Q[1][ts][sb] += ssch->Y[1][ts+s->ts_offset_hfgen][sb];
+ }
+ }
+}
+
+static int stereo_aspx_processing(AC4DecodeContext *s, Substream *ss)
+{
+ if (ss->codec_mode == CM_ASPX) {
+ aspx_processing(s, &ss->ssch[0]);
+ aspx_processing(s, &ss->ssch[1]);
+ get_qsignal_scale_factors(s, &ss->ssch[0], 0);
+ get_qsignal_scale_factors(s, &ss->ssch[1], 1);
+ get_qnoise_scale_factors(s, &ss->ssch[0], 0);
+ get_qnoise_scale_factors(s, &ss->ssch[1], 1);
+ if (ss->ssch[0].aspx_balance == 0) {
+ mono_deq_signal_factors(s, &ss->ssch[0]);
+ mono_deq_signal_factors(s, &ss->ssch[1]);
+ mono_deq_noise_factors(s, &ss->ssch[0]);
+ mono_deq_noise_factors(s, &ss->ssch[1]);
+ } else {
+ stereo_deq_signoise_factors(s, &ss->ssch[0], &ss->ssch[1]);
+ }
+ preflattening(s, &ss->ssch[0]);
+ preflattening(s, &ss->ssch[1]);
+ get_covariance(s, &ss->ssch[0]);
+ get_covariance(s, &ss->ssch[1]);
+ get_alphas(s, &ss->ssch[0]);
+ get_alphas(s, &ss->ssch[1]);
+ get_chirps(s, &ss->ssch[0]);
+ get_chirps(s, &ss->ssch[1]);
+ create_high_signal(s, ss, &ss->ssch[0]);
+ create_high_signal(s, ss, &ss->ssch[1]);
+ estimate_spectral_envelopes(s, ss, &ss->ssch[0]);
+ estimate_spectral_envelopes(s, ss, &ss->ssch[1]);
+ map_signoise(s, &ss->ssch[0]);
+ map_signoise(s, &ss->ssch[1]);
+ add_sinusoids(s, &ss->ssch[0]);
+ add_sinusoids(s, &ss->ssch[1]);
+ generate_tones(s, &ss->ssch[0]);
+ generate_tones(s, &ss->ssch[1]);
+ assemble_hf_signal(s, &ss->ssch[0]);
+ assemble_hf_signal(s, &ss->ssch[1]);
+ }
+
+ return 0;
+}
+
+static void decode_channel(AC4DecodeContext *s, int ch, float *pcm)
+{
+ Substream *ss = &s->substream;
+ SubstreamChannel *ssch = &ss->ssch[ch];
+
+ qmf_synthesis(s, ssch, pcm);
+}
+
+static int ac4_decode_frame(AVCodecContext *avctx, void *data,
+ int *got_frame_ptr, AVPacket *avpkt)
+{
+ AC4DecodeContext *s = avctx->priv_data;
+ AVFrame *frame = data;
+ GetBitContext *gb = &s->gbc;
+ int ret, start_offset = 0;
+ uint32_t header;
+
+ if (avpkt->size < 8)
+ return AVERROR_INVALIDDATA;
+
+ header = AV_RB16(avpkt->data);
+ if (header == 0xAC40 || header == 0xAC41) {
+ int size = AV_RB16(avpkt->data + 2);
+
+ start_offset = 4;
+ if (size == 0xFFFF)
+ start_offset += 3;
+ }
+
+ if ((ret = init_get_bits8(gb, avpkt->data, avpkt->size)) < 0)
+ return ret;
+ skip_bits_long(gb, start_offset * 8);
+
+ ret = ac4_toc(s);
+ if (ret < 0)
+ return ret;
+
+ if (!s->have_iframe)
+ return avpkt->size;
+
+ avctx->sample_rate = s->fs_index ? 48000 : 44100;
+ avctx->channels = channel_mode_nb_channels[s->pinfo[0].ssinfo.channel_mode];
+ avctx->channel_layout = channel_mode_layouts[s->pinfo[0].ssinfo.channel_mode];
+ frame->nb_samples = av_rescale(s->frame_len_base,
+ s->resampling_ratio.num,
+ s->resampling_ratio.den);
+ frame->nb_samples = s->frame_len_base;
+ if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
+ return ret;
+
+ skip_bits_long(gb, s->payload_base * 8);
+
+ for (int i = 0; i < s->nb_substreams; i++) {
+ int substream_type = s->substream_type[i];
+
+ switch (substream_type) {
+ case ST_SUBSTREAM:
+ ret = ac4_substream(s);
+ break;
+ case ST_PRESENTATION:
+ skip_bits_long(gb, s->substream_size[i] * 8);
+ break;
+ default:
+ av_assert0(0);
+ }
+
+ if (ret < 0)
+ return ret;
+ }
+
+ if (get_bits_left(gb) < 0)
+ av_log(s->avctx, AV_LOG_WARNING, "overread\n");
+
+ for (int ch = 0; ch < avctx->channels; ch++)
+ scale_spec(s, ch);
+
+ switch (s->pinfo[0].ssinfo.channel_mode) {
+ case 0:
+ /* nothing to do */
+ break;
+ case 1:
+ stereo_processing(s, &s->substream);
+ break;
+ case 3:
+ case 4:
+ m5channel_processing(s, &s->substream);
+ break;
+ }
+
+ for (int ch = 0; ch < avctx->channels; ch++)
+ prepare_channel(s, ch);
+
+ switch (s->pinfo[0].ssinfo.channel_mode) {
+ case 0:
+ break;
+ case 1:
+ break;
+ stereo_aspx_processing(s, &s->substream);
+ break;
+ case 3:
+ case 4:
+ break;
+ }
+
+ for (int ch = 0; ch < avctx->channels; ch++)
+ decode_channel(s, ch, (float *)frame->extended_data[ch]);
+
+ frame->key_frame = s->iframe_global;
+
+ *got_frame_ptr = 1;
+
+ return avpkt->size;
+}
+
+static av_cold void ac4_flush(AVCodecContext *avctx)
+{
+ AC4DecodeContext *s = avctx->priv_data;
+
+ s->have_iframe = 0;
+ s->sequence_counter_prev = 0;
+}
+
+static av_cold int ac4_decode_end(AVCodecContext *avctx)
+{
+ AC4DecodeContext *s = avctx->priv_data;
+
+ av_freep(&s->fdsp);
+
+ for (int j = 0; j < 8; j++)
+ for (int i = 0; i < 5; i++)
+ av_tx_uninit(&s->tx_ctx[j][i]);
+
+ return 0;
+}
+
+AVCodec ff_ac4_decoder = {
+ .name = "ac4",
+ .type = AVMEDIA_TYPE_AUDIO,
+ .id = AV_CODEC_ID_AC4,
+ .priv_data_size = sizeof (AC4DecodeContext),
+ .init = ac4_decode_init,
+ .close = ac4_decode_end,
+ .decode = ac4_decode_frame,
+ .flush = ac4_flush,
+ .capabilities = AV_CODEC_CAP_DR1,
+ .long_name = NULL_IF_CONFIG_SMALL("AC-4"),
+ .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
+ AV_SAMPLE_FMT_NONE },
+};
diff --git a/libavcodec/ac4dec_data.h b/libavcodec/ac4dec_data.h
new file mode 100644
index 0000000000..e200525399
--- /dev/null
+++ b/libavcodec/ac4dec_data.h
@@ -0,0 +1,1484 @@
+/*
+ * AC-4 Audio Decoder
+ *
+ * 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
+ */
+
+#ifndef AVCODEC_AC4DECDATA_H
+#define AVCODEC_AC4DECDATA_H
+
+static const uint8_t aspx_hcb_env_level_15_f0_bits[71] = {
+ 7, 9, 9, 9, 9, 8, 8, 7, 7, 7, 7, 7, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 4, 5,
+ 5, 5, 5, 5, 5, 5, 4, 5, 5, 5, 5, 6, 6, 6, 7, 8,
+ 9, 10, 11, 12, 14, 14, 16, 16, 17, 17, 18, 18, 18, 18, 18, 18,
+ 18, 18, 17, 17, 17, 17, 16,
+};
+
+static const uint32_t aspx_hcb_env_level_15_f0_codes[71] = {
+ 0x0003e, 0x0007e, 0x0007f, 0x000be, 0x000bf, 0x0003e, 0x0005e, 0x00016,
+ 0x00017, 0x0001e, 0x0002e, 0x0005e, 0x00012, 0x0000a, 0x0000c, 0x0000e,
+ 0x00013, 0x00016, 0x0001a, 0x0001b, 0x00022, 0x00023, 0x00004, 0x00008,
+ 0x0000c, 0x0000e, 0x00012, 0x00014, 0x00015, 0x0001a, 0x00000, 0x00016,
+ 0x00018, 0x0001e, 0x0001c, 0x00019, 0x0001d, 0x0001f, 0x00001, 0x0001b,
+ 0x00013, 0x00010, 0x0000a, 0x0002e, 0x0001e, 0x0000d, 0x0003f, 0x000be,
+ 0x0017e, 0x002fe, 0x005fe, 0x00bfe, 0x02ffe, 0x02ffc, 0x0bffc, 0x0bff6,
+ 0x17ffa, 0x17ffb, 0x2fff8, 0x2fff9, 0x2fffa, 0x2fffb, 0x2fffc, 0x2fffd,
+ 0x2fffe, 0x2ffff, 0x17fe8, 0x17fe9, 0x17fea, 0x17feb, 0x0bff7,
+};
+
+static const uint8_t aspx_hcb_env_level_15_df_bits[141] = {
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 17, 18, 19, 19, 21, 19, 19, 19, 21, 20, 20, 20, 16, 17,
+ 19, 19, 18, 18, 17, 15, 15, 15, 15, 14, 14, 14, 14, 13, 13, 13,
+ 13, 13, 13, 13, 12, 12, 12, 12, 12, 11, 10, 10, 9, 8, 8, 7,
+ 6, 6, 5, 4, 3, 2, 2, 3, 4, 6, 7, 7, 8, 9, 10, 11,
+ 11, 12, 13, 13, 14, 14, 15, 15, 15, 16, 16, 16, 17, 17, 17, 17,
+ 17, 18, 17, 17, 16, 17, 18, 19, 20, 21, 19, 19, 18, 16, 19, 21,
+ 16, 20, 20, 21, 21, 20, 20, 19, 20, 19, 17, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+};
+
+static const uint32_t aspx_hcb_env_level_15_df_codes[141] = {
+ 0xfeff2, 0xfeff3, 0xfeff4, 0xfeff5, 0xfeff6, 0xfeff7, 0xfeff8, 0xfeff9,
+ 0xfeffa, 0xfeffb, 0xfeffc, 0xfeffd, 0xfeffe, 0xfefff, 0xff5e4, 0xff5e5,
+ 0xff5e6, 0xff5e7, 0x0fef4, 0x1fefe, 0x3fdea, 0x3ffde, 0xff7b6, 0x3fdec,
+ 0x3fdee, 0x3fd78, 0xff5ee, 0x7f798, 0x7faf6, 0x7f799, 0x07ffa, 0x0fef6,
+ 0x3fdef, 0x3ffdf, 0x1fdee, 0x1ffee, 0x0ff7e, 0x03d7e, 0x03fba, 0x03fbe,
+ 0x03ffe, 0x01ebe, 0x01fdc, 0x01fee, 0x01ff6, 0x00f5c, 0x00f5d, 0x00f7e,
+ 0x00f7f, 0x00ff4, 0x00ff6, 0x00ffe, 0x007bc, 0x007bd, 0x007f6, 0x007fc,
+ 0x007fe, 0x003fa, 0x001ea, 0x001fc, 0x000f6, 0x00076, 0x0007e, 0x0003c,
+ 0x0001c, 0x0003e, 0x0001e, 0x0000e, 0x00006, 0x00002, 0x00000, 0x00002,
+ 0x00006, 0x0003f, 0x0003e, 0x0003a, 0x00077, 0x000f4, 0x001ee, 0x003fc,
+ 0x003d6, 0x007be, 0x00ffa, 0x00f5e, 0x01ff7, 0x01fea, 0x03ffc, 0x03fd6,
+ 0x03fbb, 0x07fbe, 0x07fae, 0x07f7e, 0x0fff6, 0x0fffe, 0x0fef5, 0x0fef2,
+ 0x0f5fe, 0x1fffe, 0x0ff78, 0x0fefe, 0x07afe, 0x0ff79, 0x1fef4, 0x3fd7a,
+ 0x7f79a, 0xff5ef, 0x3fdfe, 0x3fffe, 0x1fdef, 0x07ffe, 0x3fdff, 0xff5f2,
+ 0x07f78, 0x7f79b, 0x7f79e, 0xff5f3, 0xff5f4, 0x7f79f, 0x7faf8, 0x3ffff,
+ 0x7f7f8, 0x3fbce, 0x0f5ff, 0xff5f5, 0xff5f6, 0xff5f7, 0xff5f8, 0xff5f9,
+ 0xff5fa, 0xff5fb, 0xff5fc, 0xff5fd, 0xff5fe, 0xff5ff, 0xff7ac, 0xff7ad,
+ 0xff7ae, 0xff7af, 0xff7b4, 0xff7b5, 0xff7b7,
+};
+
+static const uint8_t aspx_hcb_env_level_15_dt_bits[141] = {
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 18, 18, 18, 18, 18,
+ 17, 19, 17, 16, 17, 17, 17, 16, 15, 16, 15, 15, 14, 14, 14, 13,
+ 12, 10, 8, 6, 4, 2, 1, 3, 5, 7, 10, 11, 12, 14, 14, 15,
+ 15, 16, 16, 17, 16, 17, 17, 18, 16, 17, 18, 18, 19, 18, 19, 19,
+ 17, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 18, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+};
+
+static const uint32_t aspx_hcb_env_level_15_dt_codes[141] = {
+ 0x7ffa0, 0x7ffa1, 0x7ffa2, 0x7ffa3, 0x7ffa4, 0x7ffa5, 0x7ffa6, 0x7ffa7,
+ 0x7ffa8, 0x7ffa9, 0x7ffaa, 0x7ffab, 0x7ffac, 0x7ffad, 0x7ffae, 0x7ffaf,
+ 0x7ffb0, 0x7ffb1, 0x7ffb2, 0x7ffb3, 0x7ffb4, 0x7ffb5, 0x7ffb6, 0x7ffb7,
+ 0x7ffb8, 0x7ffb9, 0x7ffba, 0x7ffbb, 0x7ffbc, 0x7ffbd, 0x7ffbe, 0x7ffbf,
+ 0x7ffc0, 0x7ffc1, 0x7ffc2, 0x7ffc3, 0x7ffc4, 0x7ffc5, 0x7ffc6, 0x7ffc7,
+ 0x7ffcc, 0x7ffcd, 0x7ffce, 0x3ff16, 0x3ff17, 0x3ff1e, 0x3ff1f, 0x3ff3c,
+ 0x1fefa, 0x7ffcf, 0x1ffb6, 0x0ff7c, 0x1ff8e, 0x1ffbe, 0x1fefb, 0x0ffc4,
+ 0x07fba, 0x0ffc6, 0x07fbb, 0x07fee, 0x03fdc, 0x03ff0, 0x03ff2, 0x01ffa,
+ 0x00ffe, 0x003fc, 0x000fe, 0x0003e, 0x0000e, 0x00002, 0x00000, 0x00006,
+ 0x0001e, 0x0007e, 0x003fe, 0x007fa, 0x00ff6, 0x03ffc, 0x03fde, 0x07fe6,
+ 0x07fec, 0x0ffda, 0x0ffde, 0x1fefe, 0x0ffce, 0x1fff2, 0x1ffbf, 0x3ff3d,
+ 0x0ff7e, 0x1feff, 0x3ff3e, 0x3ff3f, 0x7ffd2, 0x3ffe8, 0x7ffd3, 0x7ffd4,
+ 0x1ff8a, 0x3ff6e, 0x3ff6f, 0x7ffd5, 0x7ffd6, 0x7ffd7, 0x7ffd8, 0x7ffd9,
+ 0x7ffda, 0x7ffdb, 0x7ffde, 0x7ffdf, 0x3ffee, 0x7ffe0, 0x7ffe1, 0x7ffe2,
+ 0x7ffe3, 0x7ffe4, 0x7ffe5, 0x7ffe6, 0x7ffe7, 0x7ffe8, 0x7ffe9, 0x7ffea,
+ 0x7ffeb, 0x7ffec, 0x7ffed, 0x7ffee, 0x7ffef, 0x7fff0, 0x7fff1, 0x7fff2,
+ 0x7fff3, 0x7fff4, 0x7fff5, 0x7fff6, 0x7fff7, 0x7fff8, 0x7fff9, 0x7fffa,
+ 0x7fffb, 0x7fffc, 0x7fffd, 0x7fffe, 0x7ffff,
+};
+
+static const uint8_t aspx_hcb_env_balance_15_f0_bits[25] = {
+ 13, 16, 15, 15, 13, 12, 11, 9, 8, 7, 5, 3, 1, 2, 4, 7,
+ 8, 9, 10, 10, 11, 12, 13, 15, 16,
+};
+
+static const uint32_t aspx_hcb_env_balance_15_f0_codes[25] = {
+ 0x01ffe, 0x0ffea, 0x07ff6, 0x07ff7, 0x01fff, 0x00ffc, 0x007de, 0x001f6,
+ 0x000fa, 0x0007c, 0x0001e, 0x00006, 0x00000, 0x00002, 0x0000e, 0x0007e,
+ 0x000fe, 0x001fe, 0x003fe, 0x003ee, 0x007df, 0x00ffd, 0x01ffc, 0x07ff4,
+ 0x0ffeb,
+};
+
+static const uint8_t aspx_hcb_env_balance_15_df_bits[49] = {
+ 19, 19, 19, 19, 19, 18, 18, 17, 16, 16, 16, 15, 13, 13, 12, 12,
+ 12, 11, 10, 9, 8, 7, 5, 3, 1, 2, 4, 7, 8, 10, 10, 11,
+ 12, 12, 13, 13, 14, 15, 16, 18, 18, 17, 18, 18, 18, 19, 19, 18,
+ 19,
+};
+
+static const uint32_t aspx_hcb_env_balance_15_df_codes[49] = {
+ 0x7def6, 0x7def7, 0x7defa, 0x7defb, 0x7dffe, 0x3ef7c, 0x3ef7e, 0x1f7b2,
+ 0x0fbd8, 0x0fbda, 0x0fbfe, 0x07dfe, 0x01f6e, 0x01f7a, 0x00f9e, 0x00fb6,
+ 0x00fbc, 0x007da, 0x003ec, 0x001f2, 0x000fa, 0x0007e, 0x0001e, 0x00006,
+ 0x00000, 0x00002, 0x0000e, 0x0007f, 0x000f8, 0x003ee, 0x003e6, 0x007ce,
+ 0x00fbe, 0x00f9f, 0x01f7e, 0x01f6f, 0x03efe, 0x07dee, 0x0fbdb, 0x3ef78,
+ 0x3ef7f, 0x1f7b3, 0x3effc, 0x3effd, 0x3ef79, 0x7dffc, 0x7dffd, 0x3ef7a,
+ 0x7dfff,
+};
+
+static const uint8_t aspx_hcb_env_balance_15_dt_bits[49] = {
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 13, 13, 12, 12,
+ 11, 12, 11, 9, 8, 7, 4, 2, 1, 3, 5, 7, 9, 9, 10, 11,
+ 11, 12, 12, 12, 12, 13, 15, 14, 15, 14, 15, 15, 15, 14, 14, 15,
+ 15,
+};
+
+static const uint32_t aspx_hcb_env_balance_15_dt_codes[49] = {
+ 0x07dce, 0x07dcf, 0x07ddc, 0x07ddd, 0x07dde, 0x07ddf, 0x07dec, 0x07ded,
+ 0x07dee, 0x07def, 0x07df8, 0x03ebe, 0x01f5e, 0x01f7a, 0x00fb8, 0x00fba,
+ 0x007cc, 0x00fbe, 0x007d6, 0x001f2, 0x000f8, 0x0007e, 0x0000e, 0x00002,
+ 0x00000, 0x00006, 0x0001e, 0x0007f, 0x001f6, 0x001f4, 0x003ea, 0x007cd,
+ 0x007ce, 0x00f9e, 0x00fae, 0x00fbc, 0x00f9f, 0x01f76, 0x07df9, 0x03ebf,
+ 0x07dfa, 0x03ee4, 0x07dfb, 0x07dfc, 0x07dfd, 0x03ee5, 0x03ee6, 0x07dfe,
+ 0x07dff,
+};
+
+static const uint8_t aspx_hcb_env_level_30_f0_bits[36] = {
+ 11, 13, 11, 11, 10, 10, 9, 8, 8, 7, 7, 7, 6, 6, 5, 5,
+ 4, 4, 4, 4, 3, 3, 3, 3, 4, 5, 6, 7, 9, 12, 14, 16,
+ 17, 16, 17, 16,
+};
+
+static const uint32_t aspx_hcb_env_level_30_f0_codes[36] = {
+ 0x007fe, 0x01ffe, 0x001de, 0x001df, 0x000ee, 0x003fe, 0x001fe, 0x0003a,
+ 0x000fe, 0x0001c, 0x0001e, 0x0007e, 0x0002e, 0x0003e, 0x00006, 0x00016,
+ 0x00002, 0x0000a, 0x0000c, 0x0000e, 0x00002, 0x00003, 0x00004, 0x00000,
+ 0x0000d, 0x0001e, 0x0002f, 0x0001f, 0x00076, 0x00ffe, 0x03ffe, 0x0fffc,
+ 0x1fffe, 0x0fffe, 0x1ffff, 0x0fffd,
+};
+
+static const uint8_t aspx_hcb_env_level_30_df_bits[71] = {
+ 23, 23, 23, 23, 22, 22, 22, 22, 20, 19, 19, 20, 19, 18, 17, 16,
+ 16, 15, 14, 14, 14, 13, 13, 13, 13, 12, 12, 12, 11, 10, 9, 8,
+ 5, 4, 2, 1, 3, 6, 8, 9, 11, 12, 14, 14, 15, 16, 17, 17,
+ 17, 18, 18, 19, 21, 19, 17, 20, 19, 20, 20, 20, 19, 19, 19, 22,
+ 22, 22, 22, 22, 22, 22, 22,
+};
+
+static const uint32_t aspx_hcb_env_level_30_df_codes[71] = {
+ 0x7ffbfc, 0x7ffbfd, 0x7ffbfe, 0x7ffbff, 0x3f7f6c, 0x3f7f6d, 0x3f7f6e,
+ 0x3f7f6f, 0x0fdfee, 0x07effe, 0x07efec, 0x0fff7e, 0x07ffbe, 0x03f7fe,
+ 0x01fbfe, 0x00fdfc, 0x00fff6, 0x007ffa, 0x003f7e, 0x003ffc, 0x003ffe,
+ 0x001fba, 0x001fbe, 0x001ffa, 0x001ffb, 0x000fdc, 0x000ffc, 0x000ffe,
+ 0x0007fc, 0x0003f6, 0x0001fe, 0x0000fe, 0x00001e, 0x00000e, 0x000002,
+ 0x000000, 0x000006, 0x00003e, 0x0000fc, 0x0001fa, 0x0007fd, 0x000fde,
+ 0x003fff, 0x003f76, 0x007eee, 0x00fdde, 0x01ffee, 0x01fbfc, 0x01fbfa,
+ 0x03ffde, 0x03f77e, 0x07efee, 0x1ffefe, 0x07eefe, 0x01fbbe, 0x0fdfea,
+ 0x07eff6, 0x0fdfda, 0x0fdfde, 0x0fdfef, 0x07eff4, 0x07efff, 0x07eeff,
+ 0x3f7fae, 0x3f7f7c, 0x3f7f7d, 0x3f7f7e, 0x3f7f7f, 0x3f7fac, 0x3f7fad,
+ 0x3f7faf,
+};
+
+static const uint8_t aspx_hcb_env_level_30_dt_bits[71] = {
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 19, 19, 20, 20, 18, 16, 16,
+ 15, 16, 15, 14, 14, 14, 13, 13, 13, 12, 12, 11, 11, 10, 10, 8,
+ 6, 4, 2, 1, 3, 5, 8, 9, 11, 11, 12, 13, 13, 14, 14, 14,
+ 15, 15, 16, 17, 18, 19, 18, 18, 18, 18, 20, 19, 20, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 19,
+};
+
+static const uint32_t aspx_hcb_env_level_30_dt_codes[71] = {
+ 0x0ff7d6, 0x0ff7d7, 0x0ff7d8, 0x0ff7d9, 0x0ff7da, 0x0ff7db, 0x0ff7dc,
+ 0x0ff7dd, 0x0ff7de, 0x07fbfe, 0x07ed7a, 0x0ff7df, 0x0ff7f2, 0x03fdf4,
+ 0x00ff7c, 0x00fdae, 0x007ede, 0x00ff7e, 0x007ed2, 0x003f68, 0x003f6e,
+ 0x003ffa, 0x001fb6, 0x001ffe, 0x001fff, 0x000fde, 0x000ff6, 0x0007ec,
+ 0x0007fa, 0x0003fc, 0x0003fe, 0x0000fc, 0x00003e, 0x00000e, 0x000002,
+ 0x000000, 0x000006, 0x00001e, 0x0000fe, 0x0001fa, 0x0007fe, 0x0007ee,
+ 0x000fdf, 0x001ffc, 0x001fee, 0x003ffb, 0x003fde, 0x003f6a, 0x007ed6,
+ 0x007ed3, 0x00fdbe, 0x01fb7e, 0x03f6bc, 0x07fbf8, 0x03f6be, 0x03f6bf,
+ 0x03f6fe, 0x03f6ff, 0x0ff7f3, 0x07fbea, 0x0ff7f4, 0x0ff7f5, 0x0ff7f6,
+ 0x0ff7f7, 0x0ff7f8, 0x0ff7f9, 0x0ff7fa, 0x0ff7fb, 0x0ff7fe, 0x0ff7ff,
+ 0x07ed7b,
+};
+
+static const uint8_t aspx_hcb_env_balance_30_f0_bits[13] = {
+ 12, 11, 9, 7, 4, 3, 1, 2, 5, 6, 8, 10, 12,
+};
+
+static const uint16_t aspx_hcb_env_balance_30_f0_codes[13] = {
+ 0x000ffe, 0x0007fe, 0x0001fe, 0x00007e, 0x00000e, 0x000006, 0x000000,
+ 0x000002, 0x00001e, 0x00003e, 0x0000fe, 0x0003fe, 0x000fff,
+};
+
+static const uint8_t aspx_hcb_env_balance_30_df_bits[25] = {
+ 17, 17, 17, 15, 14, 12, 9, 9, 8, 7, 5, 2, 1, 3, 4, 7,
+ 8, 9, 10, 11, 14, 15, 16, 16, 17,
+};
+
+static const uint32_t aspx_hcb_env_balance_30_df_codes[25] = {
+ 0x01fffc, 0x01fffd, 0x01fffe, 0x007ffa, 0x003ffc, 0x000ffe, 0x0001fc,
+ 0x0001fe, 0x0000fa, 0x00007e, 0x00001e, 0x000002, 0x000000, 0x000006,
+ 0x00000e, 0x00007c, 0x0000fb, 0x0001fd, 0x0003fe, 0x0007fe, 0x003ffe,
+ 0x007ffb, 0x00fffc, 0x00fffd, 0x01ffff,
+};
+
+static const uint8_t aspx_hcb_env_balance_30_dt_bits[25] = {
+ 15, 15, 15, 14, 13, 13, 10, 8, 8, 7, 4, 2, 1, 3, 5, 7,
+ 9, 9, 9, 12, 14, 13, 14, 15, 14,
+};
+
+static const uint16_t aspx_hcb_env_balance_30_dt_codes[25] = {
+ 0x007ff2, 0x007ff3, 0x007ff6, 0x003ff6, 0x001ffe, 0x001fff, 0x0003fe,
+ 0x0000fa, 0x0000fe, 0x00007e, 0x00000e, 0x000002, 0x000000, 0x000006,
+ 0x00001e, 0x00007c, 0x0001fe, 0x0001f6, 0x0001f7, 0x000ffc, 0x003ffa,
+ 0x001ffa, 0x003ff7, 0x007ff7, 0x003ff8,
+};
+
+static const uint8_t aspx_hcb_noise_level_f0_bits[30] = {
+ 12, 12, 9, 7, 6, 6, 5, 1, 2, 3, 5, 7, 8, 8, 9, 10,
+ 11, 12, 12, 12, 13, 13, 14, 12, 14, 14, 11, 16, 16, 15,
+};
+
+static const uint16_t aspx_hcb_noise_level_f0_codes[30] = {
+ 0x000efe, 0x000eff, 0x0001fe, 0x000076, 0x00003a, 0x00003e, 0x00001e,
+ 0x000000, 0x000002, 0x000006, 0x00001c, 0x00007e, 0x0000fe, 0x0000ee,
+ 0x0001ff, 0x0003bc, 0x00077c, 0x000efa, 0x000ef4, 0x000ef6, 0x001df6,
+ 0x001dee, 0x003bee, 0x000ef5, 0x003bde, 0x003bef, 0x00077e, 0x00ef7e,
+ 0x00ef7f, 0x0077be,
+};
+
+static const uint8_t aspx_hcb_noise_level_df_bits[59] = {
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 13, 14, 16, 16, 15, 15,
+ 16, 15, 14, 14, 14, 14, 13, 11, 10, 9, 8, 7, 3, 1, 2, 4,
+ 5, 7, 8, 9, 10, 12, 13, 13, 14, 16, 17, 17, 17, 17, 17, 17,
+ 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+};
+
+static const uint32_t aspx_hcb_noise_level_df_codes[59] = {
+ 0x01f19e, 0x01f19f, 0x01f1dc, 0x01f1dd, 0x01f1de, 0x01f1df, 0x01f1e8,
+ 0x01f1e9, 0x01f1ea, 0x01f1eb, 0x001f1a, 0x003e7e, 0x00f9fe, 0x00f8f6,
+ 0x007c76, 0x007c66, 0x00f8f7, 0x007c7c, 0x003e3c, 0x003e36, 0x003e37,
+ 0x003e3a, 0x001f3e, 0x0007ce, 0x0003e6, 0x0001f0, 0x0000fa, 0x00007e,
+ 0x000006, 0x000000, 0x000002, 0x00000e, 0x00001e, 0x00007f, 0x0000fb,
+ 0x0001f2, 0x0003e2, 0x000f9e, 0x001f1c, 0x001f18, 0x003e32, 0x00f8fa,
+ 0x01f3fe, 0x01f1f6, 0x01f1f7, 0x01f1f8, 0x01f1f9, 0x01f1fa, 0x00f8ce,
+ 0x01f1fb, 0x01f1fc, 0x01f1fd, 0x01f1fe, 0x01f1ff, 0x01f3f8, 0x01f3f9,
+ 0x01f3fa, 0x01f3fb, 0x01f3ff,
+};
+
+static const uint8_t aspx_hcb_noise_level_dt_bits[59] = {
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 14, 16, 13, 11, 8, 6, 4, 3, 1, 2, 5,
+ 7, 10, 10, 12, 13, 13, 14, 15, 14, 15, 15, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+};
+
+static const uint16_t aspx_hcb_noise_level_dt_codes[59] = {
+ 0x00ff70, 0x00ff71, 0x00ff72, 0x00ff73, 0x00ff74, 0x00ff75, 0x00ff76,
+ 0x00ff77, 0x00ff78, 0x00ff79, 0x00ff7a, 0x00ff7b, 0x00ff7c, 0x00ff7d,
+ 0x00ff7e, 0x00ff7f, 0x00ffe0, 0x00ffe1, 0x00ffe2, 0x00ffe3, 0x00ffe6,
+ 0x003fd6, 0x00ffe7, 0x001ffe, 0x0007fe, 0x0000fe, 0x00003e, 0x00000e,
+ 0x000006, 0x000000, 0x000002, 0x00001e, 0x00007e, 0x0003fe, 0x0003fc,
+ 0x000ff6, 0x001fe8, 0x001fea, 0x003fd2, 0x007fae, 0x003fd3, 0x007ff2,
+ 0x007faf, 0x00ffe8, 0x00ffe9, 0x00ffea, 0x00ffeb, 0x00ffec, 0x00ffed,
+ 0x00ffee, 0x00ffef, 0x00fff8, 0x00fff9, 0x00fffa, 0x00fffb, 0x00fffc,
+ 0x00fffd, 0x00fffe, 0x00ffff,
+};
+
+static const uint8_t aspx_hcb_noise_balance_f0_bits[13] = {
+ 10, 10, 9, 7, 5, 3, 2, 1, 4, 6, 9, 10, 10,
+};
+
+static const uint16_t aspx_hcb_noise_balance_f0_codes[13] = {
+ 0x0003fa, 0x0003fe, 0x0001fc, 0x00007e, 0x00001e, 0x000006,
+ 0x000002, 0x000000, 0x00000e, 0x00003e, 0x0001fe, 0x0003ff,
+ 0x0003fb,
+};
+
+static const uint8_t aspx_hcb_noise_balance_df_bits[25] = {
+ 13, 13, 13, 13, 13, 12, 13, 10, 9, 7, 4, 2, 1, 3, 5, 6,
+ 9, 11, 13, 13, 12, 12, 12, 12, 12,
+};
+
+static const uint16_t aspx_hcb_noise_balance_df_codes[25] = {
+ 0x001fd8, 0x001fd9, 0x001fda, 0x001fdb, 0x001fdc, 0x000fea, 0x001fdd,
+ 0x0003f8, 0x0001fe, 0x00007e, 0x00000e, 0x000002, 0x000000, 0x000006,
+ 0x00001e, 0x00003e, 0x0001ff, 0x0007f4, 0x001fde, 0x001fdf, 0x000fe4,
+ 0x000fe5, 0x000fe6, 0x000fe7, 0x000feb,
+};
+
+static const uint8_t aspx_hcb_noise_balance_dt_bits[25] = {
+ 11, 11, 11, 11, 11, 11, 11, 10, 10, 6, 4, 3, 1, 2, 5, 8,
+ 9, 11, 10, 11, 11, 11, 11, 11, 11,
+};
+
+static const uint16_t aspx_hcb_noise_balance_dt_codes[25] = {
+ 0x0007e6, 0x0007e7, 0x0007e8, 0x0007e9, 0x0007ea, 0x0007eb, 0x0007ec,
+ 0x0003fe, 0x0003ff, 0x00003e, 0x00000e, 0x000006, 0x000000, 0x000002,
+ 0x00001e, 0x0000fe, 0x0001f8, 0x0007ed, 0x0003f2, 0x0007ee, 0x0007ef,
+ 0x0007f8, 0x0007f9, 0x0007fa, 0x0007fb,
+};
+
+static uint8_t aspx_codebook_signal_off[2][2][3] = {
+ {
+ { 0, 70, 70, },
+ { 36, 35, 35, },
+ },
+ {
+ { 25, 24, 24, },
+ { 13, 12, 12, },
+ },
+};
+
+static uint8_t aspx_codebook_noise_off[2][3] = {
+ { 30, 29, 29, },
+ { 13, 12, 12, },
+};
+
+static const uint8_t scale_factors_bits[121] = {
+ 17, 14, 14, 14, 14, 14, 14, 15, 14, 14, 14, 14, 14, 14, 14, 14,
+ 13, 13, 14, 14, 14, 14, 14, 13, 14, 13, 13, 14, 14, 13, 14, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 11,
+ 11, 11, 10, 9, 9, 8, 8, 6, 6, 4, 4, 3, 1, 4, 4, 5,
+ 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 11, 11, 12, 11, 12, 12,
+ 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14,
+ 14, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 16, 14, 14, 17,
+};
+
+static const uint8_t scale_factors_codes[121] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x01,
+ 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
+ 0x19, 0x1a, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x1b,
+ 0x14, 0x1c, 0x1d, 0x15, 0x16, 0x1e, 0x17, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x1b, 0x1c, 0x1d, 0x1e, 0x12,
+ 0x13, 0x14, 0x0d, 0x08, 0x09, 0x06, 0x07, 0x03,
+ 0x04, 0x02, 0x03, 0x03, 0x01, 0x04, 0x05, 0x03,
+ 0x05, 0x05, 0x08, 0x09, 0x0a, 0x0b, 0x0e, 0x0f,
+ 0x15, 0x16, 0x17, 0x18, 0x1f, 0x19, 0x20, 0x21,
+ 0x22, 0x23, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
+ 0x31, 0x32, 0x33, 0x34, 0x18, 0x19, 0x1a, 0x1b,
+ 0x1c, 0x35, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22,
+ 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
+ 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x01, 0x30, 0x31,
+ 0x01,
+};
+
+static const uint16_t frame_len_base_48khz[] = {
+ 1920, 1920, 2048, 1536, 1536, 960, 960, 1024,
+ 768, 768, 512, 384, 384, 2048, 0, 0,
+};
+
+static const uint8_t frame_len_base_idx_48khz[] = {
+ 1, 1, 0, 2, 2, 4, 4, 3, 5, 5, 6, 7, 7, 0, 0, 0,
+};
+
+static const uint16_t transf_length_48khz_2048[] = {
+ 128, 256, 512, 1024, 2048,
+};
+
+static const uint16_t transf_length_48khz_1920[] = {
+ 120, 240, 480, 960, 1920,
+};
+
+static const uint16_t transf_length_48khz_1536[] = {
+ 96, 192, 384, 768, 1536,
+};
+
+static const uint16_t transf_length_48khz_1024[] = {
+ 128, 256, 512, 1024, 1024,
+};
+
+static const uint16_t transf_length_48khz_960[] = {
+ 120, 240, 480, 960, 960,
+};
+
+static const uint16_t transf_length_48khz_768[] = {
+ 96, 192, 384, 768, 768,
+};
+
+static const uint16_t transf_length_48khz_512[] = {
+ 128, 256, 512, 512, 512,
+};
+
+static const uint16_t transf_length_48khz_384[] = {
+ 96, 192, 384, 384, 384,
+};
+
+static const uint16_t *transf_length_48khz[8] = {
+ transf_length_48khz_2048,
+ transf_length_48khz_1920,
+ transf_length_48khz_1536,
+ transf_length_48khz_1024,
+ transf_length_48khz_960,
+ transf_length_48khz_768,
+ transf_length_48khz_512,
+ transf_length_48khz_384,
+};
+
+static const float kbd_window_alpha[8][5] = {
+ { 6.f, 5.f, 4.5f, 4.f, 3.0f },
+ { 6.f, 5.f, 4.5f, 4.f, 3.0f },
+ { 6.f, 5.f, 4.5f, 4.f, 3.0f },
+ { 6.f, 5.f, 4.5f, 4.f, 4.0f },
+ { 6.f, 5.f, 4.5f, 4.f, 4.0f },
+ { 6.f, 5.f, 4.5f, 4.f, 4.0f },
+ { 6.f, 5.f, 4.5f, 0.f, 4.5f },
+ { 6.f, 5.f, 4.5f, 0.f, 4.5f },
+};
+
+static const uint8_t n_grp_bits_a[4][4] = {
+ { 15, 10, 8, 7 },
+ { 10, 7, 4, 3 },
+ { 8, 4, 3, 1 },
+ { 7, 3, 1, 1 },
+};
+
+static const uint8_t n_grp_bits_b[4] = {
+ 7, 3, 1, 0,
+};
+
+static const uint8_t n_grp_bits_c[4] = {
+ 3, 1, 0, 0,
+};
+
+static const uint8_t channel_mode_bits[] = {
+ 1, 2, 4, 4, 4, 7, 7, 7, 7, 7, 7, 8, 8, 9, 9, 9, 9,
+};
+
+static const uint16_t channel_mode_codes[] = {
+ 0, 2, 12, 13, 14, 120, 121, 122, 123, 124, 125, 252, 253, 508, 509, 510, 511,
+};
+
+static const uint8_t bitrate_indicator_bits[] = {
+ 3, 3, 3, 3, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+};
+
+static const uint8_t bitrate_indicator_codes[] = {
+ 0, 2, 4, 6, 4, 5, 6, 7, 12, 13, 14, 15, 20, 21, 22, 23, 28, 29, 30, 31,
+};
+
+static const uint8_t asf_codebook_dim[] = {
+ 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2,
+};
+
+static const uint8_t asf_codebook_unsigned[] = {
+ 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1,
+};
+
+static const uint8_t asf_codebook_off[] = {
+ 1, 1, 0, 0, 4, 4, 0, 0, 0, 0, 0,
+};
+
+static const uint8_t asf_codebook_mod[] = {
+ 3, 3, 3, 3, 9, 9, 8, 8, 13, 13, 17,
+};
+
+static const uint8_t asf_codebook_1_bits[81] = {
+ 9, 9, 12, 10, 7, 10, 12, 10, 11, 10, 7, 10, 7, 5, 7, 9,
+ 7, 10, 11, 8, 9, 9, 7, 9, 11, 10, 12, 9, 7, 10, 7, 5,
+ 7, 9, 7, 10, 7, 5, 7, 5, 1, 5, 7, 5, 7, 10, 7, 8,
+ 7, 5, 7, 10, 7, 9, 12, 10, 11, 9, 7, 10, 9, 8, 12, 10,
+ 7, 9, 7, 5, 7, 9, 7, 10, 12, 10, 12, 10, 7, 10, 12, 9,
+ 9,
+};
+
+static const uint8_t asf_codebook_1_codes[81] = {
+ 0x0b, 0x0c, 0x00, 0x04, 0x08, 0x05, 0x01, 0x06, 0x04, 0x07, 0x09, 0x08, 0x0a, 0x08, 0x0b, 0x0d,
+ 0x0c, 0x09, 0x05, 0x0d, 0x0e, 0x0f, 0x0d, 0x10, 0x06, 0x0a, 0x02, 0x11, 0x0e, 0x0b, 0x0f, 0x09,
+ 0x10, 0x12, 0x11, 0x0c, 0x12, 0x0a, 0x13, 0x0b, 0x01, 0x0c, 0x14, 0x0d, 0x15, 0x0d, 0x16, 0x0e,
+ 0x17, 0x0e, 0x18, 0x0e, 0x19, 0x13, 0x03, 0x0f, 0x07, 0x14, 0x1a, 0x10, 0x15, 0x0f, 0x04, 0x11,
+ 0x1b, 0x16, 0x1c, 0x0f, 0x1d, 0x17, 0x1e, 0x12, 0x05, 0x13, 0x06, 0x14, 0x1f, 0x15, 0x07, 0x18,
+ 0x19,
+};
+
+static const uint8_t asf_codebook_2_bits[81] = {
+ 8, 7, 9, 8, 6, 8, 9, 8, 9, 8, 6, 7, 6, 5, 6, 7,
+ 6, 8, 9, 7, 7, 7, 6, 7, 9, 8, 9, 8, 6, 8, 6, 5,
+ 6, 7, 6, 8, 6, 5, 6, 5, 3, 5, 6, 5, 6, 8, 6, 7,
+ 6, 5, 6, 8, 6, 8, 9, 8, 9, 8, 6, 7, 7, 7, 9, 8,
+ 6, 7, 6, 4, 6, 8, 6, 8, 9, 8, 9, 8, 6, 8, 9, 7,
+ 8,
+};
+
+static const uint8_t asf_codebook_2_codes[81] = {
+ 0x06, 0x0e, 0x00, 0x07, 0x0e, 0x08, 0x01, 0x09, 0x02, 0x0a, 0x0f, 0x0f, 0x10, 0x13, 0x11, 0x10,
+ 0x12, 0x0b, 0x03, 0x11, 0x12, 0x13, 0x13, 0x14, 0x04, 0x0c, 0x05, 0x0d, 0x14, 0x0e, 0x15, 0x14,
+ 0x16, 0x15, 0x17, 0x0f, 0x18, 0x15, 0x19, 0x16, 0x07, 0x17, 0x1a, 0x18, 0x1b, 0x10, 0x1c, 0x16,
+ 0x1d, 0x19, 0x1e, 0x11, 0x1f, 0x12, 0x06, 0x13, 0x07, 0x14, 0x20, 0x17, 0x18, 0x19, 0x08, 0x15,
+ 0x21, 0x1a, 0x22, 0x0d, 0x23, 0x16, 0x24, 0x17, 0x09, 0x18, 0x0a, 0x19, 0x25, 0x1a, 0x0b, 0x1b,
+ 0x1b,
+};
+
+static const uint8_t asf_codebook_3_bits[81] = {
+ 1, 4, 9, 4, 5, 9, 10, 10, 12, 4, 6, 10, 5, 6, 9, 10,
+ 9, 11, 10, 11, 14, 10, 10, 12, 12, 11, 13, 4, 6, 11, 6, 7,
+ 10, 11, 10, 12, 5, 7, 11, 6, 6, 10, 10, 9, 11, 9, 10, 13,
+ 9, 9, 12, 11, 11, 12, 9, 10, 15, 10, 11, 15, 14, 13, 15, 9,
+ 10, 14, 9, 10, 13, 13, 12, 14, 11, 12, 15, 11, 11, 14, 13, 12,
+ 14,
+};
+
+static const uint8_t asf_codebook_3_codes[81] = {
+ 0x01, 0x04, 0x0d, 0x05, 0x05, 0x0e, 0x0a, 0x0b, 0x05, 0x06, 0x04, 0x0c, 0x06, 0x05, 0x0f, 0x0d,
+ 0x10, 0x07, 0x0e, 0x08, 0x02, 0x0f, 0x10, 0x06, 0x07, 0x09, 0x04, 0x07, 0x06, 0x0a, 0x07, 0x06,
+ 0x11, 0x0b, 0x12, 0x08, 0x07, 0x07, 0x0c, 0x08, 0x09, 0x13, 0x14, 0x11, 0x0d, 0x12, 0x15, 0x05,
+ 0x13, 0x14, 0x09, 0x0e, 0x0f, 0x0a, 0x15, 0x16, 0x00, 0x17, 0x10, 0x01, 0x03, 0x06, 0x02, 0x16,
+ 0x18, 0x04, 0x17, 0x19, 0x07, 0x08, 0x0b, 0x05, 0x11, 0x0c, 0x03, 0x12, 0x13, 0x06, 0x09, 0x0d,
+ 0x07,
+};
+
+static const uint8_t asf_codebook_4_bits[81] = {
+ 4, 4, 9, 5, 4, 8, 9, 8, 11, 4, 5, 8, 5, 4, 8, 8,
+ 8, 10, 9, 9, 11, 8, 8, 10, 11, 10, 12, 4, 5, 8, 5, 4,
+ 8, 9, 8, 10, 4, 4, 8, 4, 4, 7, 8, 7, 9, 8, 8, 11,
+ 8, 7, 10, 10, 9, 10, 9, 8, 11, 8, 8, 11, 11, 10, 12, 8,
+ 8, 11, 8, 7, 10, 10, 9, 11, 11, 10, 12, 10, 9, 11, 12, 10,
+ 11,
+};
+
+static const uint8_t asf_codebook_4_codes[81] = {
+ 0x05, 0x06, 0x0a, 0x05, 0x07, 0x0a, 0x0b, 0x0b, 0x02, 0x08, 0x06, 0x0c, 0x07, 0x09, 0x0d, 0x0e,
+ 0x0f, 0x07, 0x0c, 0x0d, 0x03, 0x10, 0x11, 0x08, 0x04, 0x09, 0x00, 0x0a, 0x08, 0x12, 0x09, 0x0b,
+ 0x13, 0x0e, 0x14, 0x0a, 0x0c, 0x0d, 0x15, 0x0e, 0x0f, 0x10, 0x16, 0x11, 0x0f, 0x17, 0x18, 0x05,
+ 0x19, 0x12, 0x0b, 0x0c, 0x10, 0x0d, 0x11, 0x1a, 0x06, 0x1b, 0x1c, 0x07, 0x08, 0x0e, 0x01, 0x1d,
+ 0x1e, 0x09, 0x1f, 0x13, 0x0f, 0x10, 0x12, 0x0a, 0x0b, 0x11, 0x02, 0x12, 0x13, 0x0c, 0x03, 0x13,
+ 0x0d,
+};
+
+static const uint8_t asf_codebook_5_bits[81] = {
+ 14, 13, 12, 12, 11, 11, 12, 13, 14, 13, 12, 10, 9, 9, 9, 10,
+ 11, 13, 13, 10, 9, 8, 7, 7, 9, 10, 12, 12, 9, 8, 5, 4,
+ 5, 7, 9, 12, 12, 9, 7, 4, 1, 4, 7, 9, 12, 11, 9, 7,
+ 5, 4, 5, 8, 9, 12, 12, 10, 9, 7, 7, 8, 9, 10, 12, 13,
+ 11, 10, 9, 9, 10, 10, 12, 13, 14, 12, 12, 12, 11, 11, 12, 13,
+ 14,
+};
+
+static const uint8_t asf_codebook_5_codes[81] = {
+ 0x00, 0x02, 0x05, 0x06, 0x0b, 0x0c, 0x07, 0x03, 0x01, 0x04, 0x08, 0x09, 0x09, 0x0a, 0x0b, 0x0a,
+ 0x0d, 0x05, 0x06, 0x0b, 0x0c, 0x0c, 0x08, 0x09, 0x0d, 0x0c, 0x09, 0x0a, 0x0e, 0x0d, 0x04, 0x04,
+ 0x05, 0x0a, 0x0f, 0x0b, 0x0c, 0x10, 0x0b, 0x05, 0x01, 0x06, 0x0c, 0x11, 0x0d, 0x0e, 0x12, 0x0d,
+ 0x06, 0x07, 0x07, 0x0e, 0x13, 0x0e, 0x0f, 0x0d, 0x14, 0x0e, 0x0f, 0x0f, 0x15, 0x0e, 0x10, 0x07,
+ 0x0f, 0x0f, 0x16, 0x17, 0x10, 0x11, 0x11, 0x08, 0x02, 0x12, 0x13, 0x14, 0x10, 0x11, 0x15, 0x09,
+ 0x03,
+};
+
+static const uint8_t asf_codebook_6_bits[81] = {
+ 12, 11, 10, 10, 10, 10, 10, 11, 12, 11, 9, 8, 8, 8, 8, 8,
+ 9, 11, 10, 8, 6, 6, 6, 5, 6, 8, 10, 10, 8, 6, 4, 4,
+ 4, 5, 8, 10, 10, 8, 6, 4, 4, 4, 6, 8, 10, 10, 8, 5,
+ 4, 4, 4, 6, 8, 10, 10, 8, 6, 5, 6, 5, 6, 8, 11, 11,
+ 9, 8, 8, 8, 8, 8, 9, 11, 12, 11, 10, 10, 11, 10, 10, 11,
+ 12,
+};
+
+static const uint8_t asf_codebook_6_codes[81] = {
+ 0x00, 0x02, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x03, 0x01, 0x04, 0x0c, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
+ 0x0d, 0x05, 0x0b, 0x0d, 0x07, 0x08, 0x09, 0x09, 0x0a, 0x0e, 0x0c, 0x0d, 0x0f, 0x0b, 0x07, 0x08,
+ 0x09, 0x0a, 0x10, 0x0e, 0x0f, 0x11, 0x0c, 0x0a, 0x0b, 0x0c, 0x0d, 0x12, 0x10, 0x11, 0x13, 0x0b,
+ 0x0d, 0x0e, 0x0f, 0x0e, 0x14, 0x12, 0x13, 0x15, 0x0f, 0x0c, 0x10, 0x0d, 0x11, 0x16, 0x06, 0x07,
+ 0x0e, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x0f, 0x08, 0x02, 0x09, 0x14, 0x15, 0x0a, 0x16, 0x17, 0x0b,
+ 0x03,
+};
+
+static const uint8_t asf_codebook_7_bits[64] = {
+ 1, 3, 6, 8, 9, 9, 10, 11, 3, 4, 6, 7, 8, 8, 9, 10,
+ 6, 5, 7, 8, 8, 9, 10, 11, 8, 7, 8, 8, 9, 9, 10, 11,
+ 9, 8, 8, 9, 10, 10, 10, 11, 9, 8, 9, 9, 10, 10, 11, 12,
+ 10, 9, 10, 10, 10, 11, 12, 12, 12, 10, 11, 11, 12, 12, 12, 12,
+};
+
+static const uint8_t asf_codebook_7_codes[64] = {
+ 0x01, 0x02, 0x07, 0x0b, 0x0a, 0x0b, 0x06, 0x04, 0x03, 0x03, 0x08, 0x0b, 0x0c, 0x0d, 0x0c, 0x07,
+ 0x09, 0x05, 0x0c, 0x0e, 0x0f, 0x0d, 0x08, 0x05, 0x10, 0x0d, 0x11, 0x12, 0x0e, 0x0f, 0x09, 0x06,
+ 0x10, 0x13, 0x14, 0x11, 0x0a, 0x0b, 0x0c, 0x07, 0x12, 0x15, 0x13, 0x14, 0x0d, 0x0e, 0x08, 0x00,
+ 0x0f, 0x15, 0x10, 0x11, 0x12, 0x09, 0x01, 0x02, 0x03, 0x13, 0x0a, 0x0b, 0x04, 0x05, 0x06, 0x07,
+};
+
+static const uint8_t asf_codebook_8_bits[64] = {
+ 4, 4, 5, 6, 7, 8, 9, 10, 4, 3, 4, 5, 6, 7, 8, 9,
+ 5, 4, 4, 5, 6, 7, 8, 9, 6, 5, 5, 5, 6, 7, 8, 9,
+ 7, 6, 6, 6, 7, 7, 9, 10, 8, 7, 7, 7, 7, 8, 9, 10,
+ 9, 8, 8, 8, 8, 9, 9, 10, 11, 9, 9, 9, 10, 10, 10, 11,
+};
+
+static const uint8_t asf_codebook_8_codes[64] = {
+ 0x08, 0x09, 0x09, 0x0a, 0x09, 0x08, 0x04, 0x01, 0x0a, 0x07, 0x0b, 0x0a, 0x0b, 0x0a, 0x09, 0x05,
+ 0x0b, 0x0c, 0x0d, 0x0c, 0x0c, 0x0b, 0x0a, 0x06, 0x0d, 0x0d, 0x0e, 0x0f, 0x0e, 0x0c, 0x0b, 0x07,
+ 0x0d, 0x0f, 0x10, 0x11, 0x0e, 0x0f, 0x08, 0x02, 0x0c, 0x10, 0x11, 0x12, 0x13, 0x0d, 0x09, 0x03,
+ 0x0a, 0x0e, 0x0f, 0x10, 0x11, 0x0b, 0x0c, 0x04, 0x00, 0x0d, 0x0e, 0x0f, 0x05, 0x06, 0x07, 0x01,
+};
+
+static const uint8_t asf_codebook_9_bits[169] = {
+ 1, 3, 6, 8, 9, 10, 10, 11, 11, 12, 12, 12, 13, 3, 4, 6,
+ 7, 8, 9, 9, 10, 10, 11, 11, 11, 12, 6, 6, 7, 8, 9, 9,
+ 10, 10, 10, 11, 11, 12, 12, 8, 7, 8, 9, 9, 10, 10, 11, 11,
+ 11, 12, 12, 12, 9, 8, 9, 9, 10, 10, 11, 11, 11, 12, 12, 12,
+ 13, 10, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 12, 13, 10, 9,
+ 10, 10, 11, 11, 11, 12, 12, 12, 12, 13, 13, 11, 10, 10, 11, 11,
+ 12, 12, 12, 12, 12, 13, 13, 13, 11, 10, 10, 11, 11, 11, 12, 12,
+ 12, 13, 13, 13, 14, 12, 11, 11, 11, 11, 12, 12, 12, 13, 13, 13,
+ 14, 14, 12, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 12,
+ 11, 11, 12, 12, 12, 13, 13, 13, 13, 13, 14, 14, 13, 12, 12, 12,
+ 13, 13, 13, 13, 14, 14, 14, 14, 14,
+};
+
+static const uint8_t asf_codebook_9_codes[169] = {
+ 0x01, 0x02, 0x08, 0x14, 0x1b, 0x20, 0x21, 0x1e, 0x1f, 0x11, 0x12, 0x13, 0x06, 0x03, 0x03, 0x09,
+ 0x0d, 0x15, 0x1c, 0x1d, 0x22, 0x23, 0x20, 0x21, 0x22, 0x14, 0x0a, 0x0b, 0x0e, 0x16, 0x1e, 0x1f,
+ 0x24, 0x25, 0x26, 0x23, 0x24, 0x15, 0x16, 0x17, 0x0f, 0x18, 0x20, 0x21, 0x27, 0x28, 0x25, 0x26,
+ 0x27, 0x17, 0x18, 0x19, 0x22, 0x19, 0x23, 0x24, 0x29, 0x2a, 0x28, 0x29, 0x2a, 0x1a, 0x1b, 0x1c,
+ 0x07, 0x2b, 0x25, 0x26, 0x2c, 0x2d, 0x2e, 0x2b, 0x2c, 0x2d, 0x1d, 0x1e, 0x1f, 0x08, 0x2f, 0x27,
+ 0x30, 0x31, 0x2e, 0x2f, 0x30, 0x20, 0x21, 0x22, 0x23, 0x09, 0x0a, 0x31, 0x32, 0x33, 0x32, 0x33,
+ 0x24, 0x25, 0x26, 0x27, 0x28, 0x0b, 0x0c, 0x0d, 0x34, 0x34, 0x35, 0x35, 0x36, 0x37, 0x29, 0x2a,
+ 0x2b, 0x0e, 0x0f, 0x10, 0x00, 0x2c, 0x38, 0x39, 0x3a, 0x3b, 0x2d, 0x2e, 0x2f, 0x11, 0x12, 0x13,
+ 0x01, 0x02, 0x30, 0x3c, 0x3d, 0x31, 0x32, 0x33, 0x34, 0x14, 0x15, 0x16, 0x17, 0x03, 0x04, 0x35,
+ 0x3e, 0x3f, 0x36, 0x37, 0x38, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x05, 0x06, 0x1d, 0x39, 0x3a, 0x3b,
+ 0x1e, 0x1f, 0x20, 0x21, 0x07, 0x08, 0x09, 0x0a, 0x0b,
+};
+
+static const uint8_t asf_codebook_10_bits[169] = {
+ 6, 5, 6, 6, 7, 8, 9, 10, 10, 11, 11, 12, 12, 5, 4, 4,
+ 5, 6, 7, 7, 8, 9, 10, 10, 10, 11, 6, 4, 4, 5, 6, 6,
+ 7, 8, 9, 9, 10, 10, 11, 6, 5, 5, 5, 6, 7, 7, 8, 8,
+ 9, 10, 10, 11, 7, 6, 6, 6, 6, 7, 7, 8, 9, 9, 10, 10,
+ 11, 8, 7, 6, 7, 7, 7, 8, 8, 9, 9, 10, 10, 11, 9, 7,
+ 7, 7, 7, 8, 8, 9, 9, 10, 10, 10, 12, 10, 8, 8, 8, 8,
+ 8, 9, 9, 9, 10, 10, 11, 12, 10, 8, 8, 8, 8, 9, 9, 9,
+ 10, 10, 10, 11, 12, 11, 9, 9, 9, 9, 9, 10, 10, 10, 10, 11,
+ 11, 13, 11, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 13, 12,
+ 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 12, 12, 12, 11, 11, 11,
+ 11, 11, 11, 11, 12, 12, 13, 12, 13,
+};
+
+static const uint8_t asf_codebook_10_codes[169] = {
+ 0x14, 0x11, 0x15, 0x16, 0x17, 0x1a, 0x1d, 0x11, 0x12, 0x07, 0x08, 0x02, 0x03, 0x12, 0x0c, 0x0d,
+ 0x13, 0x17, 0x18, 0x19, 0x1b, 0x1e, 0x13, 0x14, 0x15, 0x09, 0x18, 0x0e, 0x0f, 0x14, 0x19, 0x1a,
+ 0x1a, 0x1c, 0x1f, 0x20, 0x16, 0x17, 0x0a, 0x1b, 0x15, 0x16, 0x17, 0x1c, 0x1b, 0x1c, 0x1d, 0x1e,
+ 0x21, 0x18, 0x19, 0x0b, 0x1d, 0x1d, 0x1e, 0x1f, 0x20, 0x1e, 0x1f, 0x1f, 0x22, 0x23, 0x1a, 0x1b,
+ 0x0c, 0x20, 0x20, 0x21, 0x21, 0x22, 0x23, 0x21, 0x22, 0x24, 0x25, 0x1c, 0x1d, 0x0d, 0x26, 0x24,
+ 0x25, 0x26, 0x27, 0x23, 0x24, 0x27, 0x28, 0x1e, 0x1f, 0x20, 0x04, 0x21, 0x25, 0x26, 0x27, 0x28,
+ 0x29, 0x29, 0x2a, 0x2b, 0x22, 0x23, 0x0e, 0x05, 0x24, 0x2a, 0x2b, 0x2c, 0x2d, 0x2c, 0x2d, 0x2e,
+ 0x25, 0x26, 0x27, 0x0f, 0x06, 0x10, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x28, 0x29, 0x2a, 0x2b, 0x11,
+ 0x12, 0x00, 0x13, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x14, 0x15, 0x16, 0x17, 0x01, 0x07,
+ 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x18, 0x19, 0x1a, 0x08, 0x09, 0x0a, 0x1b, 0x1c, 0x1d,
+ 0x1e, 0x1f, 0x20, 0x21, 0x0b, 0x0c, 0x02, 0x0d, 0x03,
+};
+
+static const uint8_t asf_codebook_11_bits[289] = {
+ 3, 4, 6, 7, 8, 9, 9, 10, 10, 11, 11, 11, 12, 12, 12, 12,
+ 10, 4, 4, 5, 6, 7, 8, 8, 9, 9, 9, 9, 10, 10, 10, 11,
+ 11, 9, 6, 5, 6, 6, 7, 7, 8, 8, 9, 9, 9, 9, 10, 10,
+ 10, 11, 8, 7, 6, 6, 7, 7, 7, 8, 8, 9, 9, 9, 9, 10,
+ 10, 10, 11, 8, 8, 7, 7, 7, 7, 8, 8, 9, 9, 9, 9, 10,
+ 10, 10, 10, 11, 8, 9, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10,
+ 10, 10, 10, 11, 11, 8, 9, 8, 8, 8, 8, 8, 9, 9, 9, 10,
+ 10, 10, 10, 10, 11, 11, 8, 10, 9, 8, 8, 8, 9, 9, 9, 9,
+ 10, 10, 10, 11, 11, 11, 11, 9, 10, 9, 9, 9, 9, 9, 9, 9,
+ 10, 10, 10, 10, 11, 11, 11, 11, 9, 11, 9, 9, 9, 9, 9, 10,
+ 10, 10, 10, 10, 10, 11, 11, 11, 12, 9, 11, 9, 9, 9, 9, 10,
+ 10, 10, 10, 10, 10, 11, 11, 11, 11, 12, 9, 11, 10, 9, 9, 9,
+ 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 12, 9, 12, 10, 10, 10,
+ 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 12, 12, 9, 11, 10, 10,
+ 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 12, 12, 12, 9, 12, 11,
+ 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 9, 12,
+ 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 9,
+ 10, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9,
+ 5,
+};
+
+static const uint8_t asf_codebook_11_codes[289] = {
+ 0x07, 0x0b, 0x1f, 0x2f, 0x3d, 0x36, 0x37, 0x26, 0x27, 0x0d, 0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03,
+ 0x28, 0x0c, 0x0d, 0x13, 0x20, 0x30, 0x3e, 0x3f, 0x38, 0x39, 0x3a, 0x3b, 0x29, 0x2a, 0x2b, 0x10,
+ 0x11, 0x3c, 0x21, 0x14, 0x22, 0x23, 0x31, 0x32, 0x40, 0x41, 0x3d, 0x3e, 0x3f, 0x40, 0x2c, 0x2d,
+ 0x2e, 0x12, 0x42, 0x33, 0x24, 0x25, 0x34, 0x35, 0x36, 0x43, 0x44, 0x41, 0x42, 0x43, 0x44, 0x2f,
+ 0x30, 0x31, 0x13, 0x45, 0x46, 0x37, 0x38, 0x39, 0x3a, 0x47, 0x48, 0x45, 0x46, 0x47, 0x48, 0x32,
+ 0x33, 0x34, 0x35, 0x14, 0x49, 0x49, 0x3b, 0x3c, 0x3d, 0x4a, 0x4b, 0x4c, 0x4a, 0x4b, 0x4c, 0x36,
+ 0x37, 0x38, 0x39, 0x15, 0x16, 0x4d, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x4e, 0x4f, 0x50, 0x3a,
+ 0x3b, 0x3c, 0x3d, 0x3e, 0x17, 0x18, 0x53, 0x3f, 0x51, 0x54, 0x55, 0x56, 0x52, 0x53, 0x54, 0x55,
+ 0x40, 0x41, 0x42, 0x19, 0x1a, 0x1b, 0x1c, 0x56, 0x43, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d,
+ 0x44, 0x45, 0x46, 0x47, 0x1d, 0x1e, 0x1f, 0x20, 0x5e, 0x21, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x48,
+ 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x22, 0x23, 0x24, 0x04, 0x64, 0x25, 0x65, 0x66, 0x67, 0x68, 0x4e,
+ 0x4f, 0x50, 0x51, 0x52, 0x53, 0x26, 0x27, 0x28, 0x29, 0x05, 0x69, 0x2a, 0x54, 0x6a, 0x6b, 0x6c,
+ 0x55, 0x56, 0x57, 0x58, 0x59, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x06, 0x6d, 0x07, 0x5a, 0x5b, 0x5c,
+ 0x5d, 0x5e, 0x5f, 0x60, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x08, 0x09, 0x6e, 0x36, 0x61, 0x62,
+ 0x63, 0x64, 0x65, 0x66, 0x67, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x0a, 0x0b, 0x0c, 0x6f, 0x0d, 0x3c,
+ 0x68, 0x69, 0x6a, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x0e, 0x0f, 0x10, 0x11, 0x70, 0x12,
+ 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x71,
+ 0x6b, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
+ 0x15,
+};
+
+static const uint16_t sfb_offset_48khz_2048[] = {
+ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40,
+ 44, 52, 60, 68, 76, 84, 92, 100, 108, 116,
+ 124, 136, 148, 160, 172, 188, 204, 220, 240,
+ 260, 284, 308, 336, 364, 396, 432, 468, 508,
+ 552, 600, 652, 704, 768, 832, 896, 960, 1024,
+ 1088, 1152, 1216, 1280, 1344, 1408, 1472, 1536,
+ 1600, 1664, 1728, 1792, 1856, 1920, 1984, 2048,
+ 2176, 2304, 2432, 2560, 2688, 2816, 2944, 3072,
+ 3200, 3328, 3456, 3584, 3712, 3840, 3968, 4096,
+ 4224, 4352, 4480, 4608, 4736, 4864, 4992, 5120,
+ 5248, 5376, 5504, 5632, 5760, 5888, 6016, 6144,
+ 6272, 6400, 6528, 6656, 6784, 6912, 7040, 7168,
+ 7296, 7424, 7552, 7680, 7808, 7936, 8064, 8192,
+};
+
+static const uint16_t sfb_offset_48khz_1920[] = {
+ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 52, 60, 68,
+ 76, 84, 92, 100, 108, 116, 124, 136, 148, 160, 172, 188,
+ 204, 220, 240, 260, 284, 308, 336, 364, 396, 432, 468,
+ 508, 552, 600, 652, 704, 768, 832, 896, 960, 1024, 1088,
+ 1152, 1216, 1280, 1344, 1408, 1472, 1536, 1600, 1664, 1728,
+ 1792, 1856, 1920, 2048, 2176, 2304, 2432, 2560, 2688, 2816,
+ 2944, 3072, 3200, 3328, 3456, 3584, 3712, 3840, 3968, 4096,
+ 4224, 4352, 4480, 4608, 4736, 4864, 4992, 5120, 5248, 5376,
+ 5504, 5632, 5760, 5888, 6016, 6144, 6272, 6400, 6528, 6656,
+ 6784, 6912, 7040, 7168, 7296, 7424, 7552, 7680,
+};
+
+static const uint16_t sfb_offset_48khz_1536[] = {
+ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40,
+ 44, 52, 60, 68, 76, 84, 92, 100, 108, 116,
+ 124, 136, 148, 160, 172, 188, 204, 220, 240,
+ 260, 284, 308, 336, 364, 396, 432, 468, 508,
+ 552, 600, 652, 704, 768, 832, 896, 960, 1024,
+ 1088, 1152, 1216, 1280, 1344, 1408, 1472, 1536,
+ 1664, 1792, 1920, 2048, 2176, 2304, 2432, 2560,
+ 2688, 2816, 2944, 3072, 3200, 3328, 3456, 3584,
+ 3712, 3840, 3968, 4096, 4224, 4352, 4480, 4608,
+ 4736, 4864, 4992, 5120, 5248, 5376, 5504, 5632,
+ 5760, 5888, 6016, 6144,
+};
+
+static const uint16_t sfb_offset_48khz_1024[] = {
+ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 48,
+ 56, 64, 72, 80, 88, 96, 108, 120, 132, 144,
+ 160, 176, 196, 216, 240, 264, 292, 320, 352,
+ 384, 416, 448, 480, 512, 544, 576, 608, 640,
+ 672, 704, 736, 768, 800, 832, 864, 896, 928,
+ 1024, 1152, 1280, 1408, 1536, 1664, 1792, 1920,
+ 2048, 2176, 2304, 2432, 2560, 2688, 2816, 2944,
+ 3072, 3200, 3328, 3456, 3584, 3712, 3840, 3968,
+ 4096,
+};
+
+static const uint16_t sfb_offset_48khz_960[] = {
+ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 48, 56, 64, 72,
+ 80, 88, 96, 108, 120, 132, 144, 160, 176, 196, 216, 240,
+ 264, 292, 320, 352, 384, 416, 448, 480, 512, 544,
+ 576, 608, 640, 672, 704, 736, 768, 800, 832, 864, 896,
+ 928, 960, 1024, 1152, 1280, 1408, 1536, 1664, 1792, 1920,
+ 2048, 2176, 2304, 2432, 2560, 2688, 2816, 2944, 3072,
+ 3200, 3328, 3456, 3584, 3712, 3840,
+};
+
+static const uint16_t sfb_offset_48khz_768[] = {
+ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 48,
+ 56, 64, 72, 80, 88, 96, 108, 120, 132, 144,
+ 160, 176, 196, 216, 240, 264, 292, 320, 352,
+ 384, 416, 448, 480, 512, 544, 576, 608, 640,
+ 672, 704, 736, 768, 896, 1024, 1152, 1280, 1408,
+ 1536, 1664, 1792, 1920, 2048, 2176, 2304, 2432,
+ 2560, 2688, 2816, 2944, 3072,
+};
+
+static const uint16_t sfb_offset_48khz_512[] = {
+ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52,
+ 56, 60, 68, 76, 84, 92, 100, 112, 124, 136, 148, 164,
+ 184, 208, 236, 268, 300, 332, 364, 396, 428, 460, 512,
+ 576, 640, 704, 768, 832, 896, 960, 1024, 1088, 1152,
+ 1216, 1280, 1344, 1408, 1472, 1536, 1600, 1664, 1728,
+ 1792, 1856, 1920, 1984, 2048,
+};
+
+static const uint16_t sfb_offset_48khz_480[] = {
+ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56,
+ 60, 68, 76, 84, 92, 100, 112, 124, 136, 148, 164, 184,
+ 208, 236, 268, 300, 332, 364, 396, 428, 460, 480, 512,
+ 576, 640, 704, 768, 832, 896, 960, 1024, 1088, 1152,
+ 1216, 1280, 1344, 1408, 1472, 1536, 1600, 1664, 1728,
+ 1792, 1856, 1920,
+};
+
+static const uint16_t sfb_offset_48khz_384[] = {
+ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52,
+ 56, 60, 68, 76, 84, 92, 100, 112, 124, 136, 148, 164,
+ 184, 208, 236, 268, 300, 332, 364, 384, 448, 512, 576,
+ 640, 704, 768, 832, 896, 960, 1024, 1088, 1152,
+ 1216, 1280, 1344, 1408, 1472, 1536,
+};
+
+static const uint16_t sfb_offset_48khz_256[] = {
+ 0, 4, 8, 12, 16, 20, 24, 28, 36, 44, 52, 64, 76,
+ 92, 108, 128, 148, 172, 196, 224, 256, 288, 320,
+ 352, 384, 416, 448, 480, 512, 576, 640, 704, 768,
+ 832, 896, 960, 1024,
+};
+
+static const uint16_t sfb_offset_48khz_240[] = {
+ 0, 4, 8, 12, 16, 20, 24, 28, 36, 44, 52, 64, 76, 92, 108,
+ 128, 148, 172, 196, 224, 240, 256, 288, 320, 352, 384, 416,
+ 448, 480, 512, 576, 640, 704, 768, 832, 896, 960,
+};
+
+static const uint16_t sfb_offset_48khz_192[] = {
+ 0, 4, 8, 12, 16, 20, 24, 28, 36, 44, 52, 64, 76,
+ 92, 108, 128, 148, 172, 192, 224, 256, 288, 320,
+ 352, 384, 448, 512, 576, 640, 704, 768,
+};
+
+static const uint16_t sfb_offset_48khz_128[] = {
+ 0, 4, 8, 12, 16, 20, 28, 36, 44, 56, 68, 80, 96, 112,
+ 128, 144, 160, 176, 192, 208, 224, 240, 256, 288, 320,
+ 352, 384, 416, 448, 480, 512,
+};
+
+static const uint16_t sfb_offset_48khz_96[] = {
+ 0, 4, 8, 12, 16, 20, 28, 36, 44, 56, 68, 80, 96, 112,
+ 128, 144, 160, 176, 192, 224, 256, 288, 320, 352, 384,
+};
+
+static const uint8_t snf_bits[22] = {
+ 4, 7, 8, 8, 7, 6, 6, 6, 6, 5, 5, 4, 4, 3, 3, 3, 3, 4, 4, 6, 7, 6,
+};
+
+static const uint8_t snf_codes[22] = {
+ 0x03, 0x01, 0x00, 0x01, 0x02, 0x02, 0x03, 0x04,
+ 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x06,
+ 0x07, 0x06, 0x07, 0x06, 0x03, 0x07,
+};
+
+static const uint8_t aspx_int_class_bits[4] = {
+ 1, 2, 3, 3,
+};
+
+static const uint8_t aspx_int_class_codes[4] = {
+ 0, 2, 6, 7,
+};
+
+static const uint8_t sbg_template_lowres[] = {
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 22, 24, 26, 28, 30, 32, 35, 38, 42, 46,
+};
+
+static const uint8_t sbg_template_highres[] = {
+ 18, 19, 20, 21, 22, 23, 24, 26, 28, 30, 32, 34,
+ 36, 38, 40, 42, 44, 47, 50, 53, 56, 59, 62,
+};
+
+static const int tab_border[5][3][5] = {
+ {
+ { 0, 6, 0, 0, 0, },
+ { 0, 3, 6, 0, 0, },
+ { 0, 2, 3, 4, 6, },
+ },
+ {
+ { 0, 8, 0, 0, 0, },
+ { 0, 4, 8, 0, 0, },
+ { 0, 2, 4, 6, 8, },
+ },
+ {
+ { 0,12, 0, 0, 0, },
+ { 0, 6,12, 0, 0, },
+ { 0, 3, 6, 9,12, },
+ },
+ {
+ { 0,15, 0, 0, 0, },
+ { 0, 8,15, 0, 0, },
+ { 0, 4, 8,12,15, },
+ },
+ {
+ { 0,16, 0, 0, 0, },
+ { 0, 8,16, 0, 0, },
+ { 0, 4, 8,12,16, },
+ },
+};
+
+static const uint8_t qmf_subbands[][4] = {
+ { 0, 0, 0, 0 },
+ { 1, 1, 1, 1 },
+ { 2, 2, 2, 2 },
+ { 3, 3, 3, 2 },
+ { 4, 4, 3, 3 },
+ { 5, 4, 4, 3 },
+ { 6, 5, 4, 3 },
+ { 7, 5, 5, 3 },
+ { 8, 6, 5, 4 },
+ { 9, 6, 6, 4 },
+ {10, 7, 6, 4 },
+ {11, 8, 7, 5 },
+ {12, 9, 7, 5 },
+ {13,10, 8, 6 },
+ {14,11, 8, 6 },
+};
+
+static const uint8_t acpl_num_param_bands[] = {
+ 15, 12, 9, 7,
+};
+
+static const uint8_t acpl_hcb_alpha_coarse_f0_bits[17] = {
+ 10, 10, 9, 8, 6, 6, 5, 2, 1, 3, 5, 7, 7, 8, 9, 10,
+ 10,
+};
+
+static const uint16_t acpl_hcb_alpha_coarse_f0_codes[17] = {
+ 0x0003be, 0x0003fe, 0x0001fe, 0x0000fe, 0x00003e, 0x00003a,
+ 0x00001e, 0x000002, 0x000000, 0x000006, 0x00001c, 0x00007e,
+ 0x000076, 0x0000ee, 0x0001de, 0x0003ff, 0x0003bf,
+};
+
+static const uint8_t acpl_hcb_alpha_fine_f0_bits[33] = {
+ 10, 12, 11, 11, 10, 10, 9, 8, 7, 7, 8, 7, 6, 6, 4, 3,
+ 1, 3, 4, 6, 6, 7, 8, 8, 9, 9, 10, 10, 10, 10, 11, 12,
+ 10,
+};
+
+static const uint16_t acpl_hcb_alpha_fine_f0_codes[33] = {
+ 0x0002ce, 0x000b5e, 0x0004fe, 0x0005ae, 0x00027e, 0x0002de,
+ 0x00016a, 0x0000b2, 0x00004a, 0x00004b, 0x0000b6, 0x00004e,
+ 0x000024, 0x00002e, 0x00000a, 0x000006, 0x000000, 0x000007,
+ 0x000008, 0x00002f, 0x000026, 0x000058, 0x0000b4, 0x00009e,
+ 0x00016e, 0x000166, 0x0002df, 0x0002cf, 0x00027c, 0x00027d,
+ 0x0004ff, 0x000b5f, 0x0002d6,
+};
+
+static const uint8_t acpl_hcb_alpha_coarse_df_bits[33] = {
+ 15, 18, 17, 17, 16, 15, 15, 13, 12, 11, 10, 9, 8, 7, 4, 3,
+ 1, 2, 5, 7, 8, 9, 10, 11, 12, 13, 15, 16, 16, 17, 16, 18,
+ 15,
+};
+
+static const uint32_t acpl_hcb_alpha_coarse_df_codes[33] = {
+ 0x007c76, 0x03e3fe, 0x01f1f6, 0x01f1f7, 0x00f8ea, 0x007c74, 0x007c7c,
+ 0x001f1c, 0x000f9e, 0x0007ce, 0x0003e2, 0x0001f0, 0x0000fa, 0x00007e,
+ 0x00000e, 0x000006, 0x000000, 0x000002, 0x00001e, 0x00007f, 0x0000fb,
+ 0x0001f2, 0x0003e6, 0x0007c6, 0x000f9f, 0x001f1e, 0x007c7e, 0x00f8fe,
+ 0x00f8fa, 0x01f1fe, 0x00f8eb, 0x03e3ff, 0x007c77,
+};
+
+static const uint8_t acpl_hcb_alpha_fine_df_bits[65] = {
+ 13, 17, 17, 17, 16, 17, 17, 17, 17, 16, 16, 16, 15, 15, 14, 13,
+ 13, 12, 12, 11, 11, 11, 10, 10, 10, 9, 8, 7, 7, 5, 4, 3,
+ 1, 3, 4, 5, 6, 7, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12,
+ 13, 13, 14, 15, 15, 16, 16, 17, 16, 16, 17, 16, 16, 17, 17, 17,
+ 13,
+};
+
+static const uint32_t acpl_hcb_alpha_fine_df_codes[65] = {
+ 0x0011de, 0x011ffe, 0x013dea, 0x013df6, 0x008eea, 0x013df7, 0x013dee,
+ 0x013deb, 0x013dec, 0x008eee, 0x008ffe, 0x009efe, 0x0047fe, 0x004f7c,
+ 0x0023fe, 0x0011fe, 0x0013fe, 0x0008f6, 0x0009ee, 0x000476, 0x00047a,
+ 0x0004f6, 0x00023a, 0x00027a, 0x00027e, 0x00013e, 0x00009a, 0x00004c,
+ 0x00004e, 0x000012, 0x00000a, 0x000006, 0x000000, 0x000007, 0x00000b,
+ 0x000010, 0x000022, 0x000046, 0x00009b, 0x00013c, 0x00011c, 0x00023e,
+ 0x00023c, 0x0004fe, 0x00047e, 0x0009fe, 0x0008fe, 0x0008f7, 0x0013ff,
+ 0x0011df, 0x0027bc, 0x004f7e, 0x004776, 0x009efa, 0x009ef4, 0x013dfe,
+ 0x008eeb, 0x008ee8, 0x013dff, 0x008ee9, 0x008eef, 0x011fff, 0x013ded,
+ 0x013def, 0x0011dc,
+};
+
+static const uint8_t acpl_hcb_alpha_coarse_dt_bits[33] = {
+ 14, 16, 15, 16, 15, 15, 14, 13, 12, 12, 10, 9, 8, 7, 5, 3,
+ 1, 2, 4, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 16, 15, 16,
+ 14,
+};
+
+static const uint32_t acpl_hcb_alpha_coarse_dt_codes[33] = {
+ 0x003efc, 0x00fbfa, 0x007ddc, 0x00fbfe, 0x007dde, 0x007dfc, 0x003ef6,
+ 0x001f76, 0x000fba, 0x000fbe, 0x0003ec, 0x0001f2, 0x0000f8, 0x00007e,
+ 0x00001e, 0x000006, 0x000000, 0x000002, 0x00000e, 0x00007f, 0x0000fa,
+ 0x0001f3, 0x0003ed, 0x0007dc, 0x000fbc, 0x001f7a, 0x003ef7, 0x007dfe,
+ 0x007ddf, 0x00fbff, 0x007ddd, 0x00fbfb, 0x003efd,
+};
+
+static const uint8_t acpl_hcb_alpha_fine_dt_bits[65] = {
+ 16, 18, 18, 18, 17, 17, 17, 18, 17, 17, 17, 16, 16, 16, 15, 15,
+ 14, 14, 13, 13, 13, 12, 11, 11, 10, 10, 9, 9, 7, 6, 5, 3,
+ 1, 2, 5, 6, 7, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14,
+ 14, 15, 15, 16, 16, 16, 17, 17, 17, 17, 17, 18, 17, 18, 18, 18,
+ 16,
+};
+
+static const uint32_t acpl_hcb_alpha_fine_dt_codes[65] = {
+ 0x00eeee, 0x03b3ee, 0x03b3f6, 0x03b3fc, 0x01d9bc, 0x01d9bd, 0x01d9b2,
+ 0x03b3fe, 0x01d9be, 0x01d9f6, 0x01d9fc, 0x00ecda, 0x00ecfa, 0x00eeef,
+ 0x00766e, 0x007776, 0x003b3a, 0x003bba, 0x001d9a, 0x001ddc, 0x001dde,
+ 0x000eec, 0x000764, 0x000772, 0x0003b0, 0x0003b8, 0x0001da, 0x0001de,
+ 0x000072, 0x000038, 0x00001e, 0x000006, 0x000000, 0x000002, 0x00001f,
+ 0x00003a, 0x000073, 0x0001df, 0x0001db, 0x0003ba, 0x0003b1, 0x000773,
+ 0x000765, 0x000eed, 0x000ecc, 0x001d9e, 0x001d9c, 0x003bbe, 0x003b3b,
+ 0x00777e, 0x00767c, 0x00eefe, 0x00ecfc, 0x00ecd8, 0x01d9fd, 0x01d9fa,
+ 0x01d9bf, 0x01d9b6, 0x01d9b3, 0x03b3fd, 0x01d9b7, 0x03b3ff, 0x03b3ef,
+ 0x03b3f7, 0x00eeff,
+};
+
+static const uint8_t acpl_hcb_beta_coarse_f0_bits[5] = {
+ 1, 2, 3, 4, 4,
+};
+
+static const uint8_t acpl_hcb_beta_coarse_f0_codes[5] = {
+ 0x000000, 0x000002, 0x000006, 0x00000e, 0x00000f,
+};
+
+static const uint8_t acpl_hcb_beta_fine_f0_bits[9] = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 8,
+};
+
+static const uint8_t acpl_hcb_beta_fine_f0_codes[9] = {
+ 0x000000, 0x000002, 0x000006, 0x00000e, 0x00001e, 0x00003e, 0x00007e, 0x0000fe, 0x0000ff,
+};
+
+static const uint8_t acpl_hcb_beta_coarse_df_bits[9] = {
+ 8, 6, 4, 3, 1, 2, 5, 7, 8,
+};
+
+static const uint8_t acpl_hcb_beta_coarse_df_codes[9] = {
+ 0x0000fe, 0x00003e, 0x00000e, 0x000006, 0x000000, 0x000002, 0x00001e, 0x00007e, 0x0000ff,
+};
+
+static const uint8_t acpl_hcb_beta_fine_df_bits[17] = {
+ 13, 12, 10, 9, 8, 7, 5, 3, 1, 2, 4, 7, 8, 9, 9, 11,
+ 13,
+};
+
+static const uint32_t acpl_hcb_beta_fine_df_codes[17] = {
+ 0x001f1e, 0x000f8e, 0x0003e2, 0x0001f2, 0x0000fa, 0x00007e,
+ 0x00001e, 0x000006, 0x000000, 0x000002, 0x00000e, 0x00007f,
+ 0x0000fb, 0x0001f3, 0x0001f0, 0x0007c6, 0x001f1f,
+};
+
+static const uint8_t acpl_hcb_beta_coarse_dt_bits[9] = {
+ 8, 7, 5, 3, 1, 2, 4, 6, 8,
+};
+
+static const uint8_t acpl_hcb_beta_coarse_dt_codes[9] = {
+ 0x0000fe, 0x00007e, 0x00001e, 0x000006, 0x000000, 0x000002, 0x00000e, 0x00003e, 0x0000ff,
+};
+
+static const uint8_t acpl_hcb_beta_fine_dt_bits[17] = {
+ 15, 14, 12, 10, 8, 7, 5, 3, 1, 2, 4, 7, 7, 9, 11, 13,
+ 15,
+};
+
+static const uint32_t acpl_hcb_beta_fine_dt_codes[17] = {
+ 0x007dfe, 0x003efe, 0x000fbe, 0x0003ee, 0x0000fa,
+ 0x00007e, 0x00001e, 0x000006, 0x000000, 0x000002,
+ 0x00000e, 0x00007f, 0x00007c, 0x0001f6, 0x0007de,
+ 0x001f7e, 0x007dff,
+};
+
+static const uint8_t acpl_hcb_beta3_coarse_f0_bits[9] = {
+ 5, 3, 3, 2, 2, 3, 4, 6, 6,
+};
+
+static const uint8_t acpl_hcb_beta3_coarse_f0_codes[9] = {
+ 0x000001, 0x000006, 0x000007, 0x000001, 0x000002, 0x000001, 0x000001, 0x000001, 0x000000,
+};
+
+static const uint8_t acpl_hcb_beta3_fine_f0_bits[17] = {
+ 7, 5, 4, 4, 4, 3, 3, 3, 3, 3, 4, 5, 6, 6, 7, 7,
+ 7,
+};
+
+static const uint8_t acpl_hcb_beta3_fine_f0_codes[17] = {
+ 0x00000d, 0x000002, 0x000000, 0x00000c, 0x00000e, 0x000001, 0x000003,
+ 0x000005, 0x000004, 0x000002, 0x00000d, 0x00001f, 0x00003d, 0x000007,
+ 0x000078, 0x00000c, 0x000079,
+};
+
+static const uint8_t acpl_hcb_beta3_coarse_df_bits[17] = {
+ 13, 12, 12, 11, 9, 6, 4, 2, 1, 3, 5, 7, 9, 11, 12, 13,
+ 9,
+};
+
+static const uint32_t acpl_hcb_beta3_coarse_df_codes[17] = {
+ 0x000a93, 0x000548, 0x00054b, 0x0002a7, 0x0000ab, 0x000014,
+ 0x000004, 0x000000, 0x000001, 0x000003, 0x00000b, 0x00002b,
+ 0x0000aa, 0x0002a6, 0x00054a, 0x000a92, 0x0000a8,
+};
+
+static const uint8_t acpl_hcb_beta3_fine_df_bits[33] = {
+ 14, 15, 14, 13, 13, 12, 11, 11, 9, 8, 7, 6, 5, 4, 3, 2,
+ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 12, 13, 14, 14, 14,
+ 15,
+};
+
+static const uint32_t acpl_hcb_beta3_fine_df_codes[33] = {
+ 0x0019e9, 0x0033f7, 0x0019f3, 0x000cf5, 0x000cfc, 0x00067d, 0x00033c,
+ 0x0007ff, 0x0000ce, 0x000066, 0x000032, 0x000018, 0x00000d, 0x000007,
+ 0x000002, 0x000000, 0x000002, 0x000006, 0x00000e, 0x00001e, 0x00003e,
+ 0x00007e, 0x0000fe, 0x0001fe, 0x0003fe, 0x0007fe, 0x00067f, 0x00067b,
+ 0x000cf8, 0x0019fa, 0x0019f2, 0x0019e8, 0x0033f6,
+};
+
+static const uint8_t acpl_hcb_beta3_coarse_dt_bits[17] = {
+ 15, 15, 14, 12, 10, 7, 5, 3, 1, 2, 4, 6, 8, 11, 14, 14,
+ 9,
+};
+
+static const uint16_t acpl_hcb_beta3_coarse_dt_codes[17] = {
+ 0x000adc, 0x000add, 0x00056c, 0x00015a, 0x000057, 0x00000b, 0x000003,
+ 0x000001, 0x000001, 0x000001, 0x000000, 0x000004, 0x000014, 0x0000ac,
+ 0x00056f, 0x00056d, 0x00002a,
+};
+
+static const uint8_t acpl_hcb_beta3_fine_dt_bits[33] = {
+ 16, 16, 16, 16, 16, 16, 15, 14, 12, 11, 10, 9, 8, 7, 5, 3,
+ 1, 2, 4, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 16, 16, 16,
+ 16,
+};
+
+static const uint32_t acpl_hcb_beta3_fine_dt_codes[33] = {
+ 0x00501e, 0x00501d, 0x00501c, 0x00501b, 0x00510e, 0x00510d, 0x002809,
+ 0x001442, 0x000500, 0x000281, 0x000141, 0x0000a1, 0x000052, 0x00002a,
+ 0x00000b, 0x000003, 0x000001, 0x000000, 0x000004, 0x00002b, 0x000053,
+ 0x0000a3, 0x000145, 0x000289, 0x000511, 0x000a20, 0x001405, 0x00280c,
+ 0x002808, 0x00510f, 0x00510c, 0x00501f, 0x00501a,
+};
+
+static const uint8_t acpl_hcb_gamma_coarse_f0_bits[21] = {
+ 13, 13, 13, 13, 11, 9, 7, 6, 5, 3, 2, 3, 3, 4, 3, 3,
+ 8, 11, 12, 13, 13,
+};
+
+static const uint16_t acpl_hcb_gamma_coarse_f0_codes[21] = {
+ 0x000af4, 0x000af8, 0x000af9, 0x000afb, 0x0002bc, 0x0000ae, 0x00002a, 0x000014,
+ 0x00000b, 0x000001, 0x000003, 0x000005, 0x000000, 0x000004, 0x000004, 0x000003,
+ 0x000056, 0x0002bf, 0x00057b, 0x000af5, 0x000afa,
+};
+
+static const uint8_t acpl_hcb_gamma_fine_f0_bits[41] = {
+ 12, 13, 13, 12, 12, 12, 12, 11, 9, 10, 9, 8, 8, 7, 7, 6,
+ 5, 5, 4, 4, 3, 3, 4, 4, 5, 5, 5, 5, 4, 3, 4, 7,
+ 8, 9, 10, 11, 11, 12, 12, 12, 12,
+};
+
+static const uint32_t acpl_hcb_gamma_fine_f0_codes[41] = {
+ 0x0004b6, 0x001c6d, 0x001c6c, 0x00049b, 0x0004b5, 0x0004b7, 0x000e35, 0x00024e,
+ 0x0001c7, 0x00038c, 0x000097, 0x000048, 0x0000e2, 0x000070, 0x000073, 0x000013,
+ 0x000008, 0x000017, 0x000005, 0x00000c, 0x000004, 0x000001, 0x00000d, 0x00000a,
+ 0x00001f, 0x00001e, 0x000016, 0x00001d, 0x000006, 0x000000, 0x000007, 0x000072,
+ 0x00004a, 0x000092, 0x00012c, 0x00024f, 0x00024c, 0x000e34, 0x0004b4, 0x00049a,
+ 0x000e37,
+};
+
+static const uint8_t acpl_hcb_gamma_coarse_df_bits[41] = {
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 14, 13, 13, 11, 10,
+ 8, 7, 4, 2, 1, 3, 5, 7, 8, 10, 11, 13, 13, 14, 15, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 8,
+};
+
+static const uint32_t acpl_hcb_gamma_coarse_df_codes[41] = {
+ 0x0053e1, 0x0053e0, 0x0053db, 0x0053da, 0x0053d9, 0x0053e2, 0x0053e4, 0x0053ea,
+ 0x0053eb, 0x0029ea, 0x0029f4, 0x0014f4, 0x000a78, 0x000a7f, 0x000299, 0x00014d,
+ 0x000051, 0x00002a, 0x000004, 0x000000, 0x000001, 0x000003, 0x00000b, 0x00002b,
+ 0x000052, 0x00014e, 0x000298, 0x000a7e, 0x000a79, 0x0014f7, 0x0029f6, 0x0053ef,
+ 0x0053ee, 0x0053e7, 0x0053e6, 0x0053e3, 0x0053e5, 0x0053d8, 0x0053d7, 0x0053d6,
+ 0x000050,
+};
+
+static const uint8_t acpl_hcb_gamma_fine_df_bits[81] = {
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 16, 16, 16, 15, 15, 15, 14, 14, 13, 13, 13, 12, 11, 11,
+ 10, 9, 8, 7, 6, 5, 4, 3, 1, 3, 4, 5, 6, 7, 9, 9,
+ 10, 11, 11, 12, 13, 13, 14, 14, 14, 15, 15, 15, 16, 16, 16, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17,
+};
+
+static const uint32_t acpl_hcb_gamma_fine_df_codes[81] = {
+ 0x013e1f, 0x013e35, 0x013e1e, 0x013e1d, 0x013e1c, 0x013e1b, 0x013e1a, 0x013e19,
+ 0x013e34, 0x013e33, 0x013e18, 0x013ec2, 0x013ec1, 0x013ece, 0x013edf, 0x013e17,
+ 0x013ede, 0x013edd, 0x009d52, 0x009f18, 0x009f1b, 0x004eaa, 0x004ea8, 0x004fb1,
+ 0x002753, 0x002757, 0x0013a8, 0x0013e0, 0x0013ee, 0x0009d6, 0x0004e9, 0x0004fa,
+ 0x00027b, 0x00013c, 0x00009c, 0x00004d, 0x000021, 0x000012, 0x00000b, 0x000007,
+ 0x000000, 0x000006, 0x00000a, 0x000011, 0x000020, 0x00004c, 0x00013f, 0x00013b,
+ 0x00027a, 0x0004f9, 0x0004e8, 0x0009d7, 0x0013ef, 0x0013e2, 0x0027da, 0x0027c7,
+ 0x002752, 0x004fb6, 0x004eac, 0x004eab, 0x009f65, 0x009d5a, 0x009d53, 0x013ecd,
+ 0x013edc, 0x013ecc, 0x013ecf, 0x013ec9, 0x013e32, 0x013ec3, 0x013e16, 0x013ec0,
+ 0x013ec8, 0x013e15, 0x013e14, 0x013e13, 0x013e12, 0x013e11, 0x013e10, 0x013ab7,
+ 0x013ab6,
+};
+
+static const uint8_t acpl_hcb_gamma_coarse_dt_bits[41] = {
+ 17, 17, 17, 17, 16, 17, 16, 16, 16, 15, 14, 13, 12, 12, 10, 9,
+ 8, 7, 5, 3, 1, 2, 4, 7, 8, 10, 11, 12, 13, 13, 14, 15,
+ 16, 16, 16, 17, 17, 17, 17, 17, 9,
+};
+
+static const uint32_t acpl_hcb_gamma_coarse_dt_codes[41] = {
+ 0x00a7f3, 0x00a7f1, 0x00a7f9, 0x00a7f8, 0x0050e1, 0x00a7fe, 0x0050e8, 0x0050eb,
+ 0x0053fe, 0x0029fd, 0x00143b, 0x000a1b, 0x00050c, 0x00053e, 0x000142, 0x0000a0,
+ 0x000052, 0x00002b, 0x00000b, 0x000003, 0x000001, 0x000000, 0x000004, 0x00002a,
+ 0x000051, 0x00014e, 0x00029e, 0x00050f, 0x000a7e, 0x000a1a, 0x001439, 0x002871,
+ 0x0050ea, 0x0050e9, 0x0050e0, 0x00a7ff, 0x00a7fb, 0x00a7fa, 0x00a7f2, 0x00a7f0,
+ 0x0000a6,
+};
+
+static const uint8_t acpl_hcb_gamma_fine_dt_bits[81] = {
+ 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 17,
+ 17, 17, 17, 17, 16, 16, 16, 15, 15, 15, 14, 14, 13, 13, 12, 12,
+ 11, 10, 9, 8, 7, 6, 5, 2, 1, 3, 5, 6, 7, 8, 10, 10,
+ 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 17, 17, 17, 17,
+ 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+ 18,
+};
+
+static const uint32_t acpl_hcb_gamma_fine_dt_codes[81] = {
+ 0x031e44, 0x031d1d, 0x031e42, 0x031e16, 0x031e41, 0x031e47, 0x031d1c, 0x031e43,
+ 0x031e73, 0x031e72, 0x031e15, 0x031e70, 0x031e75, 0x031e7f, 0x031e7e, 0x018e88,
+ 0x018d8b, 0x018e8f, 0x018f0e, 0x018f3e, 0x00c746, 0x00c796, 0x00c79e, 0x006361,
+ 0x0063c9, 0x0063d8, 0x0031d0, 0x0031e6, 0x0018d9, 0x0018f1, 0x000c6d, 0x000c7a,
+ 0x00063b, 0x00031c, 0x00018c, 0x0000c1, 0x000062, 0x000033, 0x00001b, 0x000002,
+ 0x000000, 0x000007, 0x00001a, 0x000032, 0x000061, 0x0000c0, 0x00031f, 0x00031a,
+ 0x000637, 0x000c75, 0x0018f7, 0x0018e9, 0x0031ed, 0x0031e0, 0x0063d9, 0x0063ca,
+ 0x006363, 0x006360, 0x00c786, 0x00c745, 0x018f3b, 0x018f2e, 0x018e89, 0x018d88,
+ 0x018d8a, 0x018d89, 0x031e5f, 0x031e74, 0x031e40, 0x031e71, 0x031e46, 0x031e5e,
+ 0x031e1f, 0x031e45, 0x031e1e, 0x031e14, 0x031e17, 0x031e13, 0x031e12, 0x031e11,
+ 0x031e10,
+};
+
+static const float qwin[640] = {
+ 0,
+ 1.990318758627504e-004, 2.494762615491542e-004, 3.021769445225078e-004,
+ 3.548460080857985e-004, 4.058915811480806e-004, 4.546408052001889e-004,
+ 5.012680176678405e-004, 5.464958142195282e-004, 5.912073950641334e-004,
+ 6.361178026937039e-004, 6.816060488244358e-004, 7.277257095064290e-004,
+ 7.743418255606097e-004, 8.212990636826637e-004, 8.685363488152327e-004,
+ 9.161071539925993e-004, 9.641168291303352e-004, 1.012630507392736e-003,
+ 1.061605258108620e-003, 1.110882587090581e-003, 1.160236901298543e-003,
+ 1.209448942573337e-003, 1.258362795150757e-003, 1.306902381715039e-003,
+ 1.355046337751365e-003, 1.402784629568410e-003, 1.450086694843816e-003,
+ 1.496898951224534e-003, 1.543170821958483e-003, 1.588889089195869e-003,
+ 1.634098242730728e-003, 1.678892372493930e-003, 1.723381173920660e-003,
+ 1.767651163797991e-003, 1.811741998614740e-003, 1.855650606587200e-003,
+ 1.899360915083620e-003, 1.942876625831283e-003, 1.986241654706626e-003,
+ 2.029534125962055e-003, 2.072840712410525e-003, 2.116229103721749e-003,
+ 2.159738034390673e-003, 2.203392976200947e-003, 2.247239773881968e-003,
+ 2.291373966775394e-003, 2.335946110021889e-003, 2.381132815654862e-003,
+ 2.427086732976290e-003, 2.473891839822582e-003, 2.521550367974952e-003,
+ 2.570013995199655e-003, 2.619244058999978e-003, 2.669265893796866e-003,
+ 2.720177146231281e-003, 2.772088849679780e-003, 2.825009494162980e-003,
+ 2.878716544061140e-003, 2.932677076291194e-003, 2.986067366389476e-003,
+ 3.037905983043366e-003, 3.087269477594307e-003, 3.133519274378684e-003,
+ 3.176460810085721e-003, 3.216374095471449e-003, 3.253902493849856e-003,
+ 3.289837867273167e-003, 3.324873276103132e-003, 3.359407689115599e-003,
+ 3.393454084675361e-003, 3.426668323773391e-003, 3.458465815999750e-003,
+ 3.488171121469781e-003, 3.515141351338780e-003, 3.538827383683883e-003,
+ 3.558767785536742e-003, 3.574539247363964e-003, 3.585697968628984e-003,
+ 3.591743339500398e-003, 3.592116764752254e-003, 3.586228204993297e-003,
+ 3.573492966885132e-003, 3.553356715665694e-003, 3.525300399274114e-003,
+ 3.488824092931520e-003, 3.443423145747434e-003, 3.388568319085867e-003,
+ 3.323699442173841e-003, 3.248231770523395e-003, 3.161568930730635e-003,
+ 3.063113666967670e-003, 2.952270973359112e-003, 2.828441943181057e-003,
+ 2.691016173288500e-003, 2.539366102140493e-003, 2.372848583221744e-003,
+ 2.190814088754598e-003, 1.992618085548526e-003, 1.777631090142623e-003,
+ 1.545242163079598e-003, 1.294855985911958e-003, 1.025885587325796e-003,
+ 7.377456851538827e-004, 4.298496740962311e-004, 1.016113723823784e-004,
+ -2.475493814535340e-004, -6.181972580227641e-004, -1.010876063031582e-003,
+ -1.426108207321696e-003, -1.864392667409557e-003, -2.326207721179968e-003,
+ -2.812013688448634e-003, -3.322252633537029e-003, -3.857344314546718e-003,
+ -4.417678415707104e-003, -5.003604409245843e-003, -5.615422427540850e-003,
+ -6.253382198869787e-003, -6.917691380307223e-003, -7.608536937561301e-003,
+ -8.326113472848559e-003, -9.070651572928327e-003, -9.842433610911637e-003,
+ -1.064178450184536e-002, -1.146903570409307e-002, -1.232446526717138e-002,
+ -1.320822893615923e-002, 1.412030102138547e-002, 1.506045143737221e-002,
+ 1.602824700934038e-002, 1.702310507234504e-002, 1.804435938034114e-002,
+ 1.909132707403387e-002, 2.016335321815832e-002, 2.125982139139435e-002,
+ 2.238013015948307e-002, 2.352365148441367e-002, 2.468968228813486e-002,
+ 2.587741357605385e-002, 2.708591966384863e-002, 2.831416731612567e-002,
+ 2.956103453432552e-002, 3.082532788511644e-002, 3.210578787607558e-002,
+ 3.340108247607704e-002, 3.470979250147262e-002, 3.603039785904666e-002,
+ 3.736126987823528e-002, 3.870067428980750e-002, 4.004677994303860e-002,
+ 4.139766786359423e-002, 4.275134353925827e-002, 4.410572893128047e-002,
+ 4.545866171224587e-002, 4.680788921400311e-002, 4.815106534667384e-002,
+ 4.948575188369231e-002, 5.080942296260306e-002, 5.211947012173918e-002,
+ 5.341320372603929e-002, 5.468785186395163e-002, 5.594055607104873e-002,
+ 5.716836923188953e-002, 5.836825629443718e-002, 5.953709945765930e-002,
+ 6.067170625396996e-002, 6.176881705202805e-002, 6.282510999827461e-002,
+ 6.383720245755561e-002, 6.480165083585107e-002, 6.571495100350305e-002,
+ 6.657354346196487e-002, 6.737381445564891e-002, 6.811211000439976e-002,
+ 6.878473991370719e-002, 6.938797895654626e-002, 6.991806618580000e-002,
+ 7.037120381110623e-002, 7.074355866301176e-002, 7.103126866531538e-002,
+ 7.123045563399449e-002, 7.133723888151840e-002, 7.134774334517399e-002,
+ 7.125810128129656e-002, 7.106444395777428e-002, 7.076288963679085e-002,
+ 7.034953453342756e-002, 6.982045490146145e-002, 6.917172452383333e-002,
+ 6.839944399575645e-002, 6.749977716975542e-002, 6.646898181809889e-002,
+ 6.530342654389224e-002, 6.399958984339946e-002, 6.255404354954748e-002,
+ 6.096342863203985e-002, 5.922443337469448e-002, 5.733378365410422e-002,
+ 5.528824660015738e-002, 5.308464739461209e-002, 5.071989148277166e-002,
+ 4.819098634672628e-002, 4.549505579582869e-002, 4.262934676625042e-002,
+ 3.959122947020497e-002, 3.637819581239452e-002, 3.298786054608736e-002,
+ 2.941796954479800e-002, 2.566640058060906e-002, 2.173117939155709e-002,
+ 1.761048656968719e-002, 1.330266415707108e-002, 8.806217289921706e-003,
+ 4.119815918461287e-003, -7.577038291607129e-004, -5.827337082489678e-003,
+ -1.108990619665782e-002, -1.654605559674886e-002, -2.219624707735291e-002,
+ -2.804075556277473e-002, -3.407966641908426e-002, -4.031287253355741e-002,
+ -4.674007190475649e-002, -5.336076390182971e-002, -6.017424526940620e-002,
+ -6.717960594283154e-002, -7.437572538762392e-002, -8.176127022450692e-002,
+ -8.933469320120192e-002, -9.709423309043450e-002, -1.050379143754414e-001,
+ -1.131635475471188e-001, -1.214687284677367e-001, -1.299508386078101e-001,
+ -1.386070430802319e-001, -1.474342913196958e-001, -1.564293167898782e-001,
+ -1.655886374953163e-001, -1.749085568711785e-001, -1.843851642116290e-001,
+ -1.940143360850268e-001, -2.037917371113644e-001, -2.137128217101543e-001,
+ -2.237728356363325e-001, -2.339668182208061e-001, -2.442896055908444e-001,
+ -2.547358344658102e-001, -2.652999476893712e-001, -2.759762003673840e-001,
+ -2.867586659726799e-001, -2.976412485679301e-001, -3.086176827721830e-001,
+ -3.196815399704708e-001, -3.308262316588501e-001, -3.420450091826495e-001,
+ 3.533309414505971e-001, 3.646770149404552e-001, 3.760759747758828e-001,
+ 3.875204555118187e-001, 3.990029533969267e-001, 4.105158411581483e-001,
+ 4.220513789540003e-001, 4.336017251305980e-001, 4.451589452332786e-001,
+ 4.567150149423557e-001, 4.682618290579831e-001, 4.797912086537587e-001,
+ 4.912949058677955e-001, 5.027646134968753e-001, 5.141919746376279e-001,
+ 5.255685924518015e-001, 5.368860394090674e-001, 5.481358656081351e-001,
+ 5.593096071830315e-001, 5.703987947306394e-001, 5.813949615434598e-001,
+ 5.922896536434017e-001, 6.030744392774144e-001, 6.137409201916185e-001,
+ 6.242807411441345e-001, 6.346855991963545e-001, 6.449472531836600e-001,
+ 6.550575323798634e-001, 6.650083455855346e-001, 6.747916901830467e-001,
+ 6.843996616799759e-001, 6.938244627003839e-001, 7.030584122393319e-001,
+ 7.120939537241190e-001, 7.209236637533725e-001, 7.295402599029810e-001,
+ 7.379366091028713e-001, 7.461057359576386e-001, 7.540408314942230e-001,
+ 7.617352611504460e-001, 7.691825714586890e-001, 7.763765020733762e-001,
+ 7.833109874824341e-001, 7.899801646390305e-001, 7.963783815797485e-001,
+ 8.025002033685581e-001, 8.083404191294724e-001, 8.138940486031526e-001,
+ 8.191563476989879e-001, 8.241228138607196e-001, 8.287891904413357e-001,
+ 8.331514714928793e-001, 8.372059062705359e-001, 8.409490040631689e-001,
+ 8.443775395556067e-001, 8.474885573145614e-001, 8.502793750759253e-001,
+ 8.527475863595390e-001, 8.548910606594570e-001, 8.567079441260879e-001,
+ 8.581966597760032e-001, 8.593559096378087e-001, 8.601846769933608e-001,
+ 8.606822313166693e-001, 8.608481078185764e-001, 8.606822313166693e-001,
+ 8.601846769933608e-001, 8.593559096378087e-001, 8.581966597760032e-001,
+ 8.567079441260879e-001, 8.548910606594570e-001, 8.527475863595390e-001,
+ 8.502793750759253e-001, 8.474885573145614e-001, 8.443775395556067e-001,
+ 8.409490040631689e-001, 8.372059062705359e-001, 8.331514714928793e-001,
+ 8.287891904413357e-001, 8.241228138607196e-001, 8.191563476989879e-001,
+ 8.138940486031526e-001, 8.083404191294724e-001, 8.025002033685581e-001,
+ 7.963783815797485e-001, 7.899801646390305e-001, 7.833109874824341e-001,
+ 7.763765020733762e-001, 7.691825714586890e-001, 7.617352611504460e-001,
+ 7.540408314942230e-001, 7.461057359576386e-001, 7.379366091028713e-001,
+ 7.295402599029810e-001, 7.209236637533725e-001, 7.120939537241190e-001,
+ 7.030584122393319e-001, 6.938244627003839e-001, 6.843996616799759e-001,
+ 6.747916901830467e-001, 6.650083455855346e-001, 6.550575323798634e-001,
+ 6.449472531836600e-001, 6.346855991963545e-001, 6.242807411441345e-001,
+ 6.137409201916185e-001, 6.030744392774144e-001, 5.922896536434017e-001,
+ 5.813949615434598e-001, 5.703987947306394e-001, 5.593096071830315e-001,
+ 5.481358656081351e-001, 5.368860394090674e-001, 5.255685924518015e-001,
+ 5.141919746376279e-001, 5.027646134968753e-001, 4.912949058677955e-001,
+ 4.797912086537587e-001, 4.682618290579831e-001, 4.567150149423557e-001,
+ 4.451589452332786e-001, 4.336017251305980e-001, 4.220513789540003e-001,
+ 4.105158411581483e-001, 3.990029533969267e-001, 3.875204555118187e-001,
+ 3.760759747758828e-001, 3.646770149404552e-001, -3.533309414505971e-001,
+ -3.420450091826495e-001, -3.308262316588501e-001, -3.196815399704708e-001,
+ -3.086176827721830e-001, -2.976412485679301e-001, -2.867586659726799e-001,
+ -2.759762003673840e-001, -2.652999476893712e-001, -2.547358344658102e-001,
+ -2.442896055908444e-001, -2.339668182208061e-001, -2.237728356363325e-001,
+ -2.137128217101543e-001, -2.037917371113644e-001, -1.940143360850268e-001,
+ -1.843851642116290e-001, -1.749085568711785e-001, -1.655886374953163e-001,
+ -1.564293167898782e-001, -1.474342913196958e-001, -1.386070430802319e-001,
+ -1.299508386078101e-001, -1.214687284677367e-001, -1.131635475471188e-001,
+ -1.050379143754414e-001, -9.709423309043450e-002, -8.933469320120192e-002,
+ -8.176127022450692e-002, -7.437572538762392e-002, -6.717960594283154e-002,
+ -6.017424526940620e-002, -5.336076390182971e-002, -4.674007190475649e-002,
+ -4.031287253355741e-002, -3.407966641908426e-002, -2.804075556277473e-002,
+ -2.219624707735291e-002, -1.654605559674886e-002, -1.108990619665782e-002,
+ -5.827337082489678e-003, -7.577038291607129e-004, 4.119815918461287e-003,
+ 8.806217289921706e-003, 1.330266415707108e-002, 1.761048656968719e-002,
+ 2.173117939155709e-002, 2.566640058060906e-002, 2.941796954479800e-002,
+ 3.298786054608736e-002, 3.637819581239452e-002, 3.959122947020497e-002,
+ 4.262934676625042e-002, 4.549505579582869e-002, 4.819098634672628e-002,
+ 5.071989148277166e-002, 5.308464739461209e-002, 5.528824660015738e-002,
+ 5.733378365410422e-002, 5.922443337469448e-002, 6.096342863203985e-002,
+ 6.255404354954748e-002, 6.399958984339946e-002, 6.530342654389224e-002,
+ 6.646898181809889e-002, 6.749977716975542e-002, 6.839944399575645e-002,
+ 6.917172452383333e-002, 6.982045490146145e-002, 7.034953453342756e-002,
+ 7.076288963679085e-002, 7.106444395777428e-002, 7.125810128129656e-002,
+ 7.134774334517399e-002, 7.133723888151840e-002, 7.123045563399449e-002,
+ 7.103126866531538e-002, 7.074355866301176e-002, 7.037120381110623e-002,
+ 6.991806618580000e-002, 6.938797895654626e-002, 6.878473991370719e-002,
+ 6.811211000439976e-002, 6.737381445564891e-002, 6.657354346196487e-002,
+ 6.571495100350305e-002, 6.480165083585107e-002, 6.383720245755561e-002,
+ 6.282510999827461e-002, 6.176881705202805e-002, 6.067170625396996e-002,
+ 5.953709945765930e-002, 5.836825629443718e-002, 5.716836923188953e-002,
+ 5.594055607104873e-002, 5.468785186395163e-002, 5.341320372603929e-002,
+ 5.211947012173918e-002, 5.080942296260306e-002, 4.948575188369231e-002,
+ 4.815106534667384e-002, 4.680788921400311e-002, 4.545866171224587e-002,
+ 4.410572893128047e-002, 4.275134353925827e-002, 4.139766786359423e-002,
+ 4.004677994303860e-002, 3.870067428980750e-002, 3.736126987823528e-002,
+ 3.603039785904666e-002, 3.470979250147262e-002, 3.340108247607704e-002,
+ 3.210578787607558e-002, 3.082532788511644e-002, 2.956103453432552e-002,
+ 2.831416731612567e-002, 2.708591966384863e-002, 2.587741357605385e-002,
+ 2.468968228813486e-002, 2.352365148441367e-002, 2.238013015948307e-002,
+ 2.125982139139435e-002, 2.016335321815832e-002, 1.909132707403387e-002,
+ 1.804435938034114e-002, 1.702310507234504e-002, 1.602824700934038e-002,
+ 1.506045143737221e-002, -1.412030102138547e-002, -1.320822893615923e-002,
+ -1.232446526717138e-002, -1.146903570409307e-002, -1.064178450184536e-002,
+ -9.842433610911637e-003, -9.070651572928327e-003, -8.326113472848559e-003,
+ -7.608536937561301e-003, -6.917691380307223e-003, -6.253382198869787e-003,
+ -5.615422427540850e-003, -5.003604409245843e-003, -4.417678415707104e-003,
+ -3.857344314546718e-003, -3.322252633537029e-003, -2.812013688448634e-003,
+ -2.326207721179968e-003, -1.864392667409557e-003, -1.426108207321696e-003,
+ -1.010876063031582e-003, -6.181972580227641e-004, -2.475493814535340e-004,
+ 1.016113723823784e-004, 4.298496740962311e-004, 7.377456851538827e-004,
+ 1.025885587325796e-003, 1.294855985911958e-003, 1.545242163079598e-003,
+ 1.777631090142623e-003, 1.992618085548526e-003, 2.190814088754598e-003,
+ 2.372848583221744e-003, 2.539366102140493e-003, 2.691016173288500e-003,
+ 2.828441943181057e-003, 2.952270973359112e-003, 3.063113666967670e-003,
+ 3.161568930730635e-003, 3.248231770523395e-003, 3.323699442173841e-003,
+ 3.388568319085867e-003, 3.443423145747434e-003, 3.488824092931520e-003,
+ 3.525300399274114e-003, 3.553356715665694e-003, 3.573492966885132e-003,
+ 3.586228204993297e-003, 3.592116764752254e-003, 3.591743339500398e-003,
+ 3.585697968628984e-003, 3.574539247363964e-003, 3.558767785536742e-003,
+ 3.538827383683883e-003, 3.515141351338780e-003, 3.488171121469781e-003,
+ 3.458465815999750e-003, 3.426668323773391e-003, 3.393454084675361e-003,
+ 3.359407689115599e-003, 3.324873276103132e-003, 3.289837867273167e-003,
+ 3.253902493849856e-003, 3.216374095471449e-003, 3.176460810085721e-003,
+ 3.133519274378684e-003, 3.087269477594307e-003, 3.037905983043366e-003,
+ 2.986067366389476e-003, 2.932677076291194e-003, 2.878716544061140e-003,
+ 2.825009494162980e-003, 2.772088849679780e-003, 2.720177146231281e-003,
+ 2.669265893796866e-003, 2.619244058999978e-003, 2.570013995199655e-003,
+ 2.521550367974952e-003, 2.473891839822582e-003, 2.427086732976290e-003,
+ 2.381132815654862e-003, 2.335946110021889e-003, 2.291373966775394e-003,
+ 2.247239773881968e-003, 2.203392976200947e-003, 2.159738034390673e-003,
+ 2.116229103721749e-003, 2.072840712410525e-003, 2.029534125962055e-003,
+ 1.986241654706626e-003, 1.942876625831283e-003, 1.899360915083620e-003,
+ 1.855650606587200e-003, 1.811741998614740e-003, 1.767651163797991e-003,
+ 1.723381173920660e-003, 1.678892372493930e-003, 1.634098242730728e-003,
+ 1.588889089195869e-003, 1.543170821958483e-003, 1.496898951224534e-003,
+ 1.450086694843816e-003, 1.402784629568410e-003, 1.355046337751365e-003,
+ 1.306902381715039e-003, 1.258362795150757e-003, 1.209448942573337e-003,
+ 1.160236901298543e-003, 1.110882587090581e-003, 1.061605258108620e-003,
+ 1.012630507392736e-003, 9.641168291303352e-004, 9.161071539925993e-004,
+ 8.685363488152327e-004, 8.212990636826637e-004, 7.743418255606097e-004,
+ 7.277257095064290e-004, 6.816060488244358e-004, 6.361178026937039e-004,
+ 5.912073950641334e-004, 5.464958142195282e-004, 5.012680176678405e-004,
+ 4.546408052001889e-004, 4.058915811480806e-004, 3.548460080857985e-004,
+ 3.021769445225078e-004, 2.494762615491542e-004, 1.990318758627504e-004,
+};
+
+static const float new_chirp_tab[4][4] = {
+ { 0.0, 0.6, 0.0, 0.0, },
+ { 0.6, 0.75, 0.75, 0.75, },
+ { 0.9, 0.9, 0.9, 0.9, },
+ { 0.98, 0.98, 0.98, 0.98, },
+};
+
+static const int8_t SineTable[2][4] = {
+ { 1, 0, -1, 0 },
+ { 0, 1, 0, -1 },
+};
+
+#endif /* AVCODEC_AC4DECDATA_H */
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 674995df72..a2d867abc6 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -391,6 +391,7 @@ extern AVCodec ff_ac3_encoder;
extern AVCodec ff_ac3_decoder;
extern AVCodec ff_ac3_fixed_encoder;
extern AVCodec ff_ac3_fixed_decoder;
+extern AVCodec ff_ac4_decoder;
extern AVCodec ff_acelp_kelvin_decoder;
extern AVCodec ff_alac_encoder;
extern AVCodec ff_alac_decoder;
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 5a0fc3405c..1420db26b6 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -665,6 +665,7 @@ enum AVCodecID {
AV_CODEC_ID_ACELP_KELVIN,
AV_CODEC_ID_MPEGH_3D_AUDIO,
AV_CODEC_ID_SIREN,
+ AV_CODEC_ID_AC4,
/* subtitle codecs */
AV_CODEC_ID_FIRST_SUBTITLE = 0x17000, ///< A dummy ID pointing at the start of subtitle codecs.
diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
index 52178e7afe..b01733c924 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -3058,6 +3058,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
.long_name = NULL_IF_CONFIG_SMALL("Siren"),
.props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
},
+ {
+ .id = AV_CODEC_ID_AC4,
+ .type = AVMEDIA_TYPE_AUDIO,
+ .name = "ac4",
+ .long_name = NULL_IF_CONFIG_SMALL("AC-4"),
+ .props = AV_CODEC_PROP_LOSSY,
+ },
/* subtitle codecs */
{
diff --git a/libavcodec/kbdwin.h b/libavcodec/kbdwin.h
index 4185c4206f..2ea35e1bd5 100644
--- a/libavcodec/kbdwin.h
+++ b/libavcodec/kbdwin.h
@@ -24,7 +24,7 @@
/**
* Maximum window size for ff_kbd_window_init.
*/
-#define FF_KBD_WINDOW_MAX 1024
+#define FF_KBD_WINDOW_MAX 2048
/**
* Generate a Kaiser-Bessel Derived Window.
diff --git a/libavformat/isom.c b/libavformat/isom.c
index eefe9277b4..6f4990a90c 100644
--- a/libavformat/isom.c
+++ b/libavformat/isom.c
@@ -373,6 +373,7 @@ const AVCodecTag ff_codec_movaudio_tags[] = {
{ AV_CODEC_ID_TRUEHD, MKTAG('m', 'l', 'p', 'a') }, /* mp4ra.org */
{ AV_CODEC_ID_OPUS, MKTAG('O', 'p', 'u', 's') }, /* mp4ra.org */
{ AV_CODEC_ID_MPEGH_3D_AUDIO, MKTAG('m', 'h', 'm', '1') }, /* MPEG-H 3D Audio bitstream */
+ { AV_CODEC_ID_AC4, MKTAG('a', 'c', '-', '4') }, /* ETSI TS 103 190 */
{ AV_CODEC_ID_NONE, 0 },
};
--
2.17.1
More information about the ffmpeg-devel
mailing list