From patchwork Wed Mar 4 22:26:31 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul B Mahol X-Patchwork-Id: 18025 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 6DA594484CE for ; Thu, 5 Mar 2020 00:26:58 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 413AD68B578; Thu, 5 Mar 2020 00:26:58 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wr1-f47.google.com (mail-wr1-f47.google.com [209.85.221.47]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id EBB6368B19A for ; Thu, 5 Mar 2020 00:26:51 +0200 (EET) Received: by mail-wr1-f47.google.com with SMTP id r7so4537571wro.2 for ; Wed, 04 Mar 2020 14:26:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id; bh=U8iWWFxFBLKhGq1MvyugZF/yCF7vapdDWTiLPbfVmZM=; b=vgVjB4D+edHNgiK3dCSfiYvoxUXIAhU8sSG1uAX0SpOSSjh1exvVLa2A3q7YlHMxw1 lt+2rxaeJHYQN1GP7WG1HGXcmV0YI2PtXHiwdywZDZLIMimGNAr9ZYzq77RXLnTNse6u x0Q01b+koYgGYfEP39kAljnD9pEEqVFkWpQAAMVvrV/1zjNbmiGnv40Wh+lNpF1Hc4UA sW2zUTNcIH1WRMcbA+E3VPx9+yaevt7z03BsawNDteTWBLDs3/2ayA1jcZ2qi0lx3jiG 37zhgqU2y0EqSU2DZaRECOZkltvab8drwhL8sRtObqWnM6BwauaPJakhFrzpuAp2iI9a caEQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id; bh=U8iWWFxFBLKhGq1MvyugZF/yCF7vapdDWTiLPbfVmZM=; b=hLoRUeiKubgh8b5us+rgahN6HAKzfuUaw9YYpAR/6/uTimUGj8zQLwnCoIzohrRcEo zps8shipSF2shUQxJPssW2WAhx6xqteJasJKs8WfaP1hbRNVVze5nG8fXW4S9BgPQBgj fa0bf0RBeH/QSPAU+GXL3XSVRXeNLp9iocUbz1XVLTumOVAD+FqI+W8ohp13ek29IE/8 BUiznEd5z/YX/dUnNrbqWwR6dFvVTb8dRd1V/PZ3F5T6fdzndeHFRTZAQ3sslhu4eyM6 /IK9Hw5rpltGXqSfes6v4PI6GHMMaL1wM/EiZMUyMBBiW0RWpZzTKiChBVDnDgeahNrV vqAA== X-Gm-Message-State: ANhLgQ2PXQDR8nU8y2XKK9yMxqGXV6GGlKJHLxbkS+I7I0xkwZiZE6hV /ZNSQKq1+Ewx8PF9VrlZG0gJsXTh X-Google-Smtp-Source: ADFU+vuAMEEAFQ93jRtMKVhgK7ex1FeozQHL1kszbztceA7ul/PrwLX718SdKxze4qp0h6pnCS8lCA== X-Received: by 2002:adf:82a3:: with SMTP id 32mr5932719wrc.290.1583360808297; Wed, 04 Mar 2020 14:26:48 -0800 (PST) Received: from localhost.localdomain ([109.227.41.139]) by smtp.gmail.com with ESMTPSA id 133sm6618096wmd.5.2020.03.04.14.26.43 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Mar 2020 14:26:47 -0800 (PST) From: Paul B Mahol To: ffmpeg-devel@ffmpeg.org Date: Wed, 4 Mar 2020 23:26:31 +0100 Message-Id: <20200304222633.12177-1-onemda@gmail.com> X-Mailer: git-send-email 2.17.1 Subject: [FFmpeg-devel] [RFC][WIP][PATCH 1/3] avcodec: add AC-4 decoder X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" This work is sponsored by VideoLAN. Signed-off-by: Paul B Mahol --- 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 }, }; From patchwork Wed Mar 4 22:26:32 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul B Mahol X-Patchwork-Id: 18027 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 2D8AF44ACEA for ; Thu, 5 Mar 2020 00:33:00 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 0C80E68B51C; Thu, 5 Mar 2020 00:33:00 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wm1-f65.google.com (mail-wm1-f65.google.com [209.85.128.65]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 31F4A689D14 for ; Thu, 5 Mar 2020 00:32:54 +0200 (EET) Received: by mail-wm1-f65.google.com with SMTP id p9so4053188wmc.2 for ; Wed, 04 Mar 2020 14:32:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references; bh=9xCnPd51kP4vkES8nX/0xDBexfl5W220C7Tme+loMR4=; b=DyD+AJFCJ53NAjIaa9SefpMFw1CjO7BXc2XQ2GeBO4h5m2sBNPziz8Qp2UGBfOwG8d MEF5imRy+/ZdtTzv9IPoSTJhqgrHyNp8/NQcoh8gIv1HKQQSuvCNaNE6DNLdB53Wr2CN R0mEk40RTQmyaHh5nfyCwNkk5b5CBgVauZXSDDY7lFMWQtZoUdinzc7s1n9TvdowIPlM 8XZfRfBePN+xdhV4xOo4/uJi5IyDycYjwfh/NtQFD2xnhOLAHwb0jI7UMBiZPj67cDPs JeIYxJZnmj8h+RcASUrRaW18py7R3tTKhzrCgtX6olwklepByBc1mZFt4Lfo81VXhrsE 79Ng== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=9xCnPd51kP4vkES8nX/0xDBexfl5W220C7Tme+loMR4=; b=sVppcvgXl+KsIP50aLIR4YjTTTlnDhZQlX1p7SnwR4FpieG3EdywGXtqrFeVGs7ExV 8qtjVV844i1X9Qmi267kvshygzRGd3tI5Ff8RH0uisje6Emzc8g4ZPzicn0bjky1NTV8 Oxpb8ckr5Ce4GM3Dz96pDgLeMPsNKqd+ZFCgTFPRGMiipIKXHv7J4lddkAJjH/fO7I/u ELXlBMC/1Engsn63Tn+7tu2e7tVNUN7Ai9K6oHZRYESC4XJN2eemq1/sa2yBhNJNwy5D v2VwgalmybLnhLbKFEzYEQNgFZx89B/tNo9bbxLUdreFylQX+RmB8qj9tPcXVnSLInCm OyCQ== X-Gm-Message-State: ANhLgQ2nlR/hUksdINtko0YcrOqD2WXiahijA0oCRwfH1JfAfIqj7tfp ceYJSWwnzXVdX9RZn/mX0VOjJOEr X-Google-Smtp-Source: ADFU+vt5dDtYFGZZAMNvTc+/KcIc0auPepYWSs0cjvL3k9YXwj/SIX+YkOzQqhVxF+GFWI2CIfSSfA== X-Received: by 2002:a7b:c148:: with SMTP id z8mr1148397wmi.174.1583360809359; Wed, 04 Mar 2020 14:26:49 -0800 (PST) Received: from localhost.localdomain ([109.227.41.139]) by smtp.gmail.com with ESMTPSA id 133sm6618096wmd.5.2020.03.04.14.26.48 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Mar 2020 14:26:48 -0800 (PST) From: Paul B Mahol To: ffmpeg-devel@ffmpeg.org Date: Wed, 4 Mar 2020 23:26:32 +0100 Message-Id: <20200304222633.12177-2-onemda@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200304222633.12177-1-onemda@gmail.com> References: <20200304222633.12177-1-onemda@gmail.com> Subject: [FFmpeg-devel] [PATCH 2/3] avformat: add raw AC-4 demuxer X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Signed-off-by: Paul B Mahol --- libavformat/Makefile | 1 + libavformat/ac4dec.c | 104 +++++++++++++++++++++++++++++++++++++++ libavformat/allformats.c | 1 + 3 files changed, 106 insertions(+) create mode 100644 libavformat/ac4dec.c diff --git a/libavformat/Makefile b/libavformat/Makefile index e0681058a2..b4e8d20e65 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -70,6 +70,7 @@ OBJS-$(CONFIG_AA_DEMUXER) += aadec.o OBJS-$(CONFIG_AAC_DEMUXER) += aacdec.o apetag.o img2.o rawdec.o OBJS-$(CONFIG_AC3_DEMUXER) += ac3dec.o rawdec.o OBJS-$(CONFIG_AC3_MUXER) += rawenc.o +OBJS-$(CONFIG_AC4_DEMUXER) += ac4dec.o OBJS-$(CONFIG_ACM_DEMUXER) += acm.o rawdec.o OBJS-$(CONFIG_ACT_DEMUXER) += act.o OBJS-$(CONFIG_ADF_DEMUXER) += bintext.o sauce.o diff --git a/libavformat/ac4dec.c b/libavformat/ac4dec.c new file mode 100644 index 0000000000..8c6e539409 --- /dev/null +++ b/libavformat/ac4dec.c @@ -0,0 +1,104 @@ +/* + * RAW AC-4 demuxer + * 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 + */ + +#include "libavutil/avassert.h" +#include "libavutil/crc.h" +#include "avformat.h" +#include "rawdec.h" + +static int ac4_probe(const AVProbeData *p) +{ + const uint8_t *buf = p->buf; + int left = p->buf_size; + int max_frames = 0; + + while (left > 7) { + int size; + + if (buf[0] == 0xAC && + (buf[1] == 0x40 || + buf[1] == 0x41)) { + size = (buf[2] << 8) | buf[3]; + if (size == 0xFFFF) + size = 3 + (buf[4] << 16) | (buf[5] << 8) | buf[6]; + size += 4; + if (buf[1] == 0x41) + size += 2; + max_frames++; + left -= size; + buf += size; + } else { + break; + } + } + + return FFMIN(AVPROBE_SCORE_MAX, max_frames * 7); +} + +static int ac4_read_header(AVFormatContext *s) +{ + AVStream *st; + + st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_AC4; + + return 0; +} + +static int ac4_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + AVIOContext *pb = s->pb; + int64_t pos; + uint16_t sync; + int ret, size; + + if (avio_feof(s->pb)) + return AVERROR_EOF; + + pos = avio_tell(s->pb); + sync = avio_rb16(pb); + size = avio_rb16(pb); + if (size == 0xffff) + size = avio_rb24(pb); + + ret = av_get_packet(pb, pkt, size); + pkt->pos = pos; + pkt->stream_index = 0; + + if (sync == 0xAC41) + avio_skip(pb, 2); + + return ret; +} + +AVInputFormat ff_ac4_demuxer = { + .name = "ac4", + .long_name = NULL_IF_CONFIG_SMALL("raw AC-4"), + .read_probe = ac4_probe, + .read_header = ac4_read_header, + .read_packet = ac4_read_packet, + .flags = AVFMT_GENERIC_INDEX, + .extensions = "ac4", +}; diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 0209bf0e30..d2afcb2bdd 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -33,6 +33,7 @@ extern AVInputFormat ff_aa_demuxer; extern AVInputFormat ff_aac_demuxer; extern AVInputFormat ff_ac3_demuxer; extern AVOutputFormat ff_ac3_muxer; +extern AVInputFormat ff_ac4_demuxer; extern AVInputFormat ff_acm_demuxer; extern AVInputFormat ff_act_demuxer; extern AVInputFormat ff_adf_demuxer; From patchwork Wed Mar 4 22:26:33 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul B Mahol X-Patchwork-Id: 18024 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 6FFA64484CE for ; Thu, 5 Mar 2020 00:26:57 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 4EBB368B4A0; Thu, 5 Mar 2020 00:26:57 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wr1-f67.google.com (mail-wr1-f67.google.com [209.85.221.67]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 41BB768AF69 for ; Thu, 5 Mar 2020 00:26:51 +0200 (EET) Received: by mail-wr1-f67.google.com with SMTP id v2so4495286wrp.12 for ; Wed, 04 Mar 2020 14:26:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references; bh=R/xuZ0v3DyaVcoapVA+0NJqmRKahOJTqDxNp2RNEWTg=; b=KKvFQzeJfjOSrn+3Zi/CTuSWT2cqL6rF9dz1HLJgpFaU67TAdzlRasNqfTY+9gLuWr jDTkVzUjDim/oDoTY123thkWD+FxyH+fKzlzqGXPSkh9NA50wUb7XBHOi28ZpYbpp45z lA28FxHvjtv6ZTZxoFJAGzO0tP7RM3pomnz9LkecyjtEVR1UpyEzse8dqeC5LH3OeO8S Mch5i7iKJwDifP1np3w+r2ujcOp5FYg6vgjcVg+03zPtgNRxXhnFLoZIcLynPlEoy7XC cgMuzQADa4exgFreDrfGyh5kCCaG5bWgyJ3ya+JDiZFJ88MSzRB0jFBFaMsVbDpCZAve Pafg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=R/xuZ0v3DyaVcoapVA+0NJqmRKahOJTqDxNp2RNEWTg=; b=ep2RG2chRp5XwlN1wxSDGwsesMechksk5VDsxUjx+MpIwoCQrndAmRfyLJDHR/7en7 bNBh0bXjdOYpp3+hyMycWaDdvm8OSMEErE8fQI1cLnUTCHnLJgKxxA1VtdseS94qYIPD 9lZhu44RPmf4CbGZhY4HLKRg86GbFXwi87kfztrUqknoJHIixMZeqztnbO+bxreYtz/k 7tiELZK01/cEEJyE+bpaLYsM4d5RFtviCjOcsooGWHkSB6DPf4SGqiCT/HSSAZIQipcL 7yTjDnmyg0JrK9IVq/Dn7Yd7Jro/tl/hw1/I+BeNQJkcHwedyAfcJdQJfGvlCxZq5m0p quyg== X-Gm-Message-State: ANhLgQ2iDeaKZeT/6i7fumfahP49vGzjl7jgwfxK5H+hFjVxNTYft0hK OQGFQWGhJqfCwto0dUPaPVdUDPsk X-Google-Smtp-Source: ADFU+vuonrglliMAWjwKGH00dnKE5gyQdtb3tVqLABsxhql1mJ/nYI6nAORF9kDT2Row79O0fFwJLA== X-Received: by 2002:adf:ed42:: with SMTP id u2mr6298602wro.345.1583360810357; Wed, 04 Mar 2020 14:26:50 -0800 (PST) Received: from localhost.localdomain ([109.227.41.139]) by smtp.gmail.com with ESMTPSA id 133sm6618096wmd.5.2020.03.04.14.26.49 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Mar 2020 14:26:49 -0800 (PST) From: Paul B Mahol To: ffmpeg-devel@ffmpeg.org Date: Wed, 4 Mar 2020 23:26:33 +0100 Message-Id: <20200304222633.12177-3-onemda@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200304222633.12177-1-onemda@gmail.com> References: <20200304222633.12177-1-onemda@gmail.com> Subject: [FFmpeg-devel] [PATCH 3/3] mpegts hack X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Signed-off-by: Paul B Mahol --- libavformat/mpegts.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index 7f56bacb2c..782f13fe4f 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -955,8 +955,8 @@ static int mpegts_set_stream_info(AVStream *st, PESContext *pes, (st->request_probe > 0 && st->request_probe < AVPROBE_SCORE_STREAM_RETRY / 5)) && st->probe_packets > 0 && stream_type == STREAM_TYPE_PRIVATE_DATA) { - st->codecpar->codec_type = AVMEDIA_TYPE_DATA; - st->codecpar->codec_id = AV_CODEC_ID_BIN_DATA; + st->codecpar->codec_type = pes->stream_type == 6 ? AVMEDIA_TYPE_AUDIO : AVMEDIA_TYPE_DATA; + st->codecpar->codec_id = pes->stream_type == 6 ? AV_CODEC_ID_AC4 : AV_CODEC_ID_BIN_DATA; st->request_probe = AVPROBE_SCORE_STREAM_RETRY / 5; } @@ -2062,6 +2062,13 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type av_dict_set(&st->metadata, "language", language, 0); } } + if (ext_desc_tag == 0x15) { /* AC-4 descriptor */ + st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + st->codecpar->codec_id = AV_CODEC_ID_AC4; + st->request_probe = 0; + + st->internal->need_context_update = 1; + } break; case 0x6a: /* ac-3_descriptor */ {