[dev-dependencies]
nihav_flash = { path = "../nihav-flash", default-features=false, features = ["all_demuxers"] }
nihav_realmedia = { path = "../nihav-realmedia", default-features=false, features = ["all_demuxers"] }
+nihav_commonfmt = { path = "../nihav-commonfmt", default-features=false, features = ["all_demuxers"] }
[features]
default = ["all_decoders"]
use coeff_read::*;
mod info;
use info::*;
+mod sbr;
+use sbr::{SBRHeader, SBRCodebooks, SBRState, SBRChannel, SBRDSP, sbr_read_sce, sbr_read_cpe};
#[allow(clippy::excessive_precision)]
mod tables;
use tables::*;
ms_mask_present: u8,
ms_used: [[bool; MAX_SFBS]; MAX_WINDOWS],
ics: [ICS; 2],
+ sbr_hdr: SBRHeader,
+ sbr_state: SBRState,
+ sbr_ch: [SBRChannel; 2],
+ do_sbr: bool,
}
impl ChannelPair {
ms_mask_present: 0,
ms_used: [[false; MAX_SFBS]; MAX_WINDOWS],
ics: [ICS::new(sbinfo), ICS::new(sbinfo)],
+ sbr_hdr: SBRHeader::new(),
+ sbr_state: SBRState::new(),
+ sbr_ch: [SBRChannel::new(), SBRChannel::new()],
+ do_sbr: false,
}
}
fn decode_ga_sce(&mut self, br: &mut BitReader, codebooks: &Codebooks, m4atype: M4AType) -> DecoderResult<()> {
}
Ok(())
}
- fn synth_audio(&mut self, dsp: &mut DSP, abuf: &mut NABufferType, srate_idx: usize) {
+ fn decode_sbr(&mut self, buf: &[u8], has_crc: bool, cbs: &SBRCodebooks, srate: u32) -> DecoderResult<()> {
+ let mut br = BitReader::new(buf, BitReaderMode::BE);
+ if has_crc {
+ let _bs_sbr_crc_bits = br.read(10)?;
+ }
+ if br.read_bool()? {
+ if let Ok(hdr) = SBRHeader::read(&mut br) {
+ if self.sbr_hdr.differs_from(&hdr) {
+ self.do_sbr = self.sbr_state.init(&hdr, srate).is_ok();
+ self.sbr_ch[0].reset();
+ self.sbr_ch[1].reset();
+ }
+ self.sbr_hdr = hdr;
+ } else {
+ self.do_sbr = false;
+ }
+ }
+ if self.do_sbr {
+ if !self.pair {
+ sbr_read_sce(&mut br, self.sbr_hdr.amp_res, &self.sbr_state, cbs, &mut self.sbr_ch[0])?;
+ } else {
+ sbr_read_cpe(&mut br, self.sbr_hdr.amp_res, &self.sbr_state, cbs, &mut self.sbr_ch)?;
+ }
+ }
+
+ Ok(())
+ }
+ fn synth_audio(&mut self, dsp: &mut DSP, abuf: &mut NABufferType, srate_idx: usize, upsample: bool) {
let mut adata = abuf.get_abuf_f32().unwrap();
let output = adata.get_data_mut().unwrap();
let off0 = abuf.get_offset(self.channel);
let off1 = abuf.get_offset(self.channel + 1);
- self.ics[0].synth_channel(dsp, &mut output[off0..], srate_idx);
- if self.pair {
- self.ics[1].synth_channel(dsp, &mut output[off1..], srate_idx);
+ if !upsample {
+ self.ics[0].synth_channel(dsp, &mut output[off0..], srate_idx);
+ if self.pair {
+ self.ics[1].synth_channel(dsp, &mut output[off1..], srate_idx);
+ }
+ } else {
+ let mut tmp = [0.0; 1024];
+ let nchannels = if self.pair { 2 } else { 1 };
+ for ch in 0..nchannels {
+ let off = if ch == 0 { off0 } else { off1 };
+ self.ics[ch].synth_channel(dsp, &mut tmp, srate_idx);
+ self.sbr_ch[ch].analysis(&mut dsp.sbr_dsp, &tmp);
+ if self.do_sbr {
+ self.sbr_ch[ch].hf_generate(&self.sbr_state);
+ self.sbr_ch[ch].hf_adjust(&self.sbr_state, &self.sbr_hdr);
+ } else {
+ self.sbr_ch[ch].bypass();
+ }
+ self.sbr_ch[ch].synthesis(&mut dsp.sbr_dsp, &mut output[off..][..2048]);
+ self.sbr_ch[ch].update_frame();
+ }
}
}
}
imdct_short: IMDCT,
tmp: [f32; 2048],
ew_buf: [f32; 1152],
+ sbr_dsp: SBRDSP,
}
const SHORT_WIN_POINT0: usize = 512 - 64;
imdct_long: IMDCT::new(1024 * 2, true),
imdct_short: IMDCT::new(128 * 2, true),
tmp: [0.0; 2048], ew_buf: [0.0; 1152],
+ sbr_dsp: SBRDSP::new(),
}
}
#[allow(clippy::cognitive_complexity)]
codebooks: Codebooks,
dsp: DSP,
sbinfo: GASubbandInfo,
+ sbr_cbs: SBRCodebooks,
+ upsample: bool,
}
impl AACDecoder {
codebooks: Codebooks::new(),
dsp: DSP::new(),
sbinfo: AAC_SUBBAND_INFO[0],
+ sbr_cbs: SBRCodebooks::new(),
+ upsample: false,
}
}
fn set_pair(&mut self, pair_no: usize, channel: usize, pair: bool) -> DecoderResult<()> {
count += br.read(8)? as usize;
count -= 1;
}
- for _ in 0..count {
- // ext payload
+ if count > 0 {
+ let extension_type = br.read(4)?;
+ match extension_type {
+ 0xD | 0xE => { // SBR data without or with CRC
+ let has_crc = extension_type == 0xE;
+
+ let mut buf = [0; 256 + 16];
+ for el in buf[..count - 1].iter_mut() {
+ *el = br.read(8)? as u8;
+ }
+ buf[count - 1] = br.read(4)? as u8;
+ if cur_pair > 0 {
+ self.pairs[cur_pair - 1].decode_sbr(&buf[..count], has_crc, &self.sbr_cbs, self.m4ainfo.srate * 2)?;
+ }
+ },
+ _ => {
+ for _ in 0..count-1 {
br.skip(8)?;
+ }
+ br.skip(4)?;
+ },
+ };
}
},
7 => { // ID_TERM
}
let srate_idx = GASubbandInfo::find_idx(self.m4ainfo.srate);
for pair in 0..cur_pair {
- self.pairs[pair].synth_audio(&mut self.dsp, abuf, srate_idx);
+ self.pairs[pair].synth_audio(&mut self.dsp, abuf, srate_idx, self.upsample);
}
Ok(())
}
}
self.sbinfo = GASubbandInfo::find(self.m4ainfo.srate);
- let ainfo = NAAudioInfo::new(self.m4ainfo.srate, self.m4ainfo.channels as u8,
- SND_F32P_FORMAT, self.m4ainfo.samples);
+ self.upsample = self.m4ainfo.srate < 32000;
+ let (srate, samples) = if !self.upsample {
+ (self.m4ainfo.srate, self.m4ainfo.samples)
+ } else {
+ (self.m4ainfo.srate * 2, self.m4ainfo.samples * 2)
+ };
+
+ let ainfo = NAAudioInfo::new(srate, self.m4ainfo.channels as u8,
+ SND_F32P_FORMAT, samples);
self.info = info.replace_info(NACodecTypeInfo::Audio(ainfo));
if self.m4ainfo.channels >= DEFAULT_CHANNEL_MAP.len() {
let pktbuf = pkt.get_buffer();
let ainfo = self.info.get_properties().get_audio_info().unwrap();
- let mut abuf = alloc_audio_buffer(ainfo, self.m4ainfo.samples, self.chmap.clone())?;
+ let samples = if !self.upsample { self.m4ainfo.samples } else { self.m4ainfo.samples * 2 };
+ let mut abuf = alloc_audio_buffer(ainfo, samples, self.chmap.clone())?;
let mut br = BitReader::new(&pktbuf, BitReaderMode::BE);
match self.m4ainfo.otype {
let file = "assets/RV/rv40_weighted_mc_2.rmvb";
test_decode_audio("realmedia", file, Some(12000), None/*Some("aac")*/, &dmx_reg, &dec_reg);
}
+ #[test]
+ fn test_aac_sbr() {
+ let mut dmx_reg = RegisteredDemuxers::new();
+ nihav_commonfmt::generic_register_all_demuxers(&mut dmx_reg);
+ let mut dec_reg = RegisteredDecoders::new();
+ mpeg_register_all_decoders(&mut dec_reg);
+
+ let file = "assets/MPEG/SBRtestStereoAot29Sig0.mp4";
+ test_decode_audio("mov", file, Some(400), None/*Some("aacsbr")*/, &dmx_reg, &dec_reg);
+ }
}
const DEFAULT_CHANNEL_MAP: [&str; 9] = [
--- /dev/null
+use nihav_core::codecs::{DecoderResult, DecoderError};
+use nihav_core::io::bitreader::*;
+use nihav_core::io::codebook::*;
+
+use super::{MAX_SLOTS, NUM_ENVELOPES, SBR_BANDS, SBRState, SBRChannel};
+use super::synth::QuantMode;
+
+#[derive(Clone,Copy,Debug,PartialEq)]
+pub enum FrameClass {
+ FixFix,
+ FixVar,
+ VarFix,
+ VarVar,
+}
+
+impl FrameClass {
+ fn read(br: &mut BitReader) -> DecoderResult<Self> {
+ Ok(match br.read(2)? {
+ 0 => Self::FixFix,
+ 1 => Self::FixVar,
+ 2 => Self::VarFix,
+ _ => Self::VarVar,
+ })
+ }
+}
+
+pub fn sbr_read_sce(br: &mut BitReader, orig_amp_res: bool, state: &SBRState, cbs: &SBRCodebooks, ch: &mut SBRChannel) -> DecoderResult<()> {
+ ch.qmode = QuantMode::Single;
+ if br.read_bool()? {
+ br.skip(4)?;
+ }
+ read_grid(br, ch)?;
+ read_dtdf(br, ch)?;
+ read_invf(br, ch, state)?;
+ ch.set_amp_res(orig_amp_res);
+ read_envelope(br, ch, false, cbs, state)?;
+ read_noise(br, ch, false, cbs, state)?;
+ read_sinusoidal_coding(br, ch, state)?;
+ read_extensions(br)?;
+
+ Ok(())
+}
+pub fn sbr_read_cpe(br: &mut BitReader, orig_amp_res: bool, state: &SBRState, cbs: &SBRCodebooks, ch: &mut [SBRChannel; 2]) -> DecoderResult<()> {
+ if br.read_bool()? {
+ br.skip(4)?;
+ br.skip(4)?;
+ }
+ let coupling = br.read_bool()?;
+ if coupling {
+ ch[0].qmode = QuantMode::Left;
+ ch[1].qmode = QuantMode::Right;
+ read_grid(br, &mut ch[0])?;
+ ch[1].fclass = ch[0].fclass;
+ ch[1].num_env = ch[0].num_env;
+ ch[1].env_border = ch[0].env_border;
+ ch[1].freq_res = ch[0].freq_res;
+ ch[1].pointer = ch[0].pointer;
+ ch[1].num_noise = ch[0].num_noise;
+ ch[1].noise_env_border = ch[0].noise_env_border;
+
+ read_dtdf(br, &mut ch[0])?;
+ read_dtdf(br, &mut ch[1])?;
+ read_invf(br, &mut ch[0], state)?;
+ ch[1].invf_mode = ch[0].invf_mode;
+
+ ch[0].set_amp_res(orig_amp_res);
+ read_envelope(br, &mut ch[0], false, cbs, state)?;
+ read_noise(br, &mut ch[0], false, cbs, state)?;
+ ch[1].set_amp_res(orig_amp_res);
+ read_envelope(br, &mut ch[1], true, cbs, state)?;
+ read_noise(br, &mut ch[1], true, cbs, state)?;
+
+ ch[0].data_env2 = ch[1].data_env;
+ ch[0].data_noise2 = ch[1].data_noise;
+ ch[1].data_env2 = ch[0].data_env;
+ ch[1].data_noise2 = ch[0].data_noise;
+ } else {
+ ch[0].qmode = QuantMode::Single;
+ ch[1].qmode = QuantMode::Single;
+ read_grid(br, &mut ch[0])?;
+ read_grid(br, &mut ch[1])?;
+ read_dtdf(br, &mut ch[0])?;
+ read_dtdf(br, &mut ch[1])?;
+ read_invf(br, &mut ch[0], state)?;
+ read_invf(br, &mut ch[1], state)?;
+
+ ch[0].set_amp_res(orig_amp_res);
+ read_envelope(br, &mut ch[0], false, cbs, state)?;
+ ch[1].set_amp_res(orig_amp_res);
+ read_envelope(br, &mut ch[1], false, cbs, state)?;
+ read_noise(br, &mut ch[0], false, cbs, state)?;
+ read_noise(br, &mut ch[1], false, cbs, state)?;
+ }
+ read_sinusoidal_coding(br, &mut ch[0], state)?;
+ read_sinusoidal_coding(br, &mut ch[1], state)?;
+ read_extensions(br)?;
+
+ Ok(())
+}
+
+fn read_grid(br: &mut BitReader, chan: &mut SBRChannel) -> DecoderResult<()> {
+ chan.fclass = FrameClass::read(br)?;
+ match chan.fclass {
+ FrameClass::FixFix => {
+ chan.num_env = 1 << br.read(2)?;
+ let freq_res = br.read_bool()?;
+ for el in chan.freq_res[..chan.num_env].iter_mut() {
+ *el = freq_res;
+ }
+ if chan.num_env > 1 {
+ let delta = (MAX_SLOTS + chan.num_env / 2) / chan.num_env;
+ chan.env_border[0] = delta;
+ for i in 0..chan.num_env - 1 {
+ chan.env_border[i + 1] = chan.env_border[i] + delta;
+ }
+ }
+ chan.env_border[chan.num_env - 1] = MAX_SLOTS;
+ },
+ FrameClass::FixVar => {
+ let var_bord_1 = br.read(2)? as u8;
+ chan.num_env = br.read(2)? as usize + 1;
+ let mut rel_bord_1 = [0u8; NUM_ENVELOPES];
+ for el in rel_bord_1[..chan.num_env - 1].iter_mut() {
+ *el = 2 * (br.read(2)? as u8) + 2;
+ }
+ let ptr_bits = 8 - (chan.num_env as u8).leading_zeros();
+ chan.pointer = br.read(ptr_bits as u8)? as u8;
+ for el in chan.freq_res[..chan.num_env].iter_mut().rev() {
+ *el = br.read_bool()?;
+ }
+
+ chan.env_border[chan.num_env - 1] = MAX_SLOTS + usize::from(var_bord_1);
+ for (i, &delta) in (1..chan.num_env).rev().zip(rel_bord_1.iter()) {
+ chan.env_border[i - 1] = chan.env_border[i] - usize::from(delta);
+ }
+ },
+ FrameClass::VarFix => {
+ let var_bord_0 = br.read(2)? as u8;
+ chan.num_env = br.read(2)? as usize + 1;
+ let mut rel_bord_0 = [0u8; NUM_ENVELOPES];
+ for el in rel_bord_0[..chan.num_env - 1].iter_mut() {
+ *el = 2 * (br.read(2)? as u8) + 2;
+ }
+ let ptr_bits = 8 - (chan.num_env as u8).leading_zeros();
+ chan.pointer = br.read(ptr_bits as u8)? as u8;
+ for el in chan.freq_res[..chan.num_env].iter_mut() {
+ *el = br.read_bool()?;
+ }
+
+ chan.env_border[0] = usize::from(var_bord_0 + rel_bord_0[0]);
+ for i in 1..chan.num_env {
+ chan.env_border[i] = chan.env_border[i - 1] + usize::from(rel_bord_0[i]);
+ }
+ chan.env_border[chan.num_env - 1] = MAX_SLOTS;
+ },
+ FrameClass::VarVar => {
+ let var_bord_0 = br.read(2)? as u8;
+ let var_bord_1 = br.read(2)? as u8;
+ let num_rel_0 = br.read(2)? as usize;
+ let num_rel_1 = br.read(2)? as usize;
+ chan.num_env = (num_rel_0 as usize) + (num_rel_1 as usize) + 1;
+ let mut rel_bord_0 = [0u8; NUM_ENVELOPES];
+ let mut rel_bord_1 = [0u8; NUM_ENVELOPES];
+ for el in rel_bord_0[..num_rel_0].iter_mut() {
+ *el = 2 * (br.read(2)? as u8) + 2;
+ }
+ for el in rel_bord_1[..num_rel_1].iter_mut() {
+ *el = 2 * (br.read(2)? as u8) + 2;
+ }
+ let ptr_bits = 8 - (chan.num_env as u8).leading_zeros();
+ chan.pointer = br.read(ptr_bits as u8)? as u8;
+ for el in chan.freq_res[..chan.num_env].iter_mut() {
+ *el = br.read_bool()?;
+ }
+
+ chan.env_border[0] = usize::from(var_bord_0 + rel_bord_0[0]);
+ for i in 1..=num_rel_0 {
+ chan.env_border[i] = chan.env_border[i - 1] + usize::from(rel_bord_0[i]);
+ }
+ chan.env_border[chan.num_env - 1] = MAX_SLOTS + usize::from(var_bord_1);
+ for i in 0..num_rel_1 {
+ chan.env_border[chan.num_env - 2 - i] = chan.env_border[chan.num_env - 1 - i] - usize::from(rel_bord_1[i]);
+ }
+ },
+ };
+ for i in 0..chan.num_env - 1 {
+ validate!(chan.env_border[i] < chan.env_border[i + 1]);
+ }
+
+ if chan.num_env > 1 {
+ chan.num_noise = 2;
+ let mid = match (chan.fclass, chan.pointer) {
+ (FrameClass::FixFix, _) => chan.num_env / 2 - 1,
+ (FrameClass::VarFix, 0) => 0,
+ (FrameClass::VarFix, 1) => chan.num_env - 2,
+ (FrameClass::VarFix, _) => chan.pointer as usize - 2,
+ (_, 0) | (_, 1) => chan.num_env - 2,
+ (_, _) => chan.num_env - (chan.pointer as usize),
+ };
+ chan.noise_env_border[0] = chan.env_border[mid];
+ chan.noise_env_border[1] = chan.env_border[chan.num_env - 1];
+ } else {
+ chan.num_noise = 1;
+ chan.noise_env_border[0] = chan.env_border[0];
+ }
+
+
+ Ok(())
+}
+fn read_dtdf(br: &mut BitReader, chan: &mut SBRChannel) -> DecoderResult<()> {
+ for el in chan.df_env[..chan.num_env].iter_mut() {
+ *el = br.read_bool()?;
+ }
+ for el in chan.df_noise[..chan.num_noise].iter_mut() {
+ *el = br.read_bool()?;
+ }
+ Ok(())
+}
+fn read_invf(br: &mut BitReader, chan: &mut SBRChannel, state: &SBRState) -> DecoderResult<()> {
+ for el in chan.invf_mode[..state.num_noise_bands].iter_mut() {
+ *el = br.read(2)? as u8;
+ }
+ Ok(())
+}
+fn read_envelope(br: &mut BitReader, chan: &mut SBRChannel, coupled: bool, cbs: &SBRCodebooks, state: &SBRState) -> DecoderResult<()> {
+ let (f_cb, t_cb) = if coupled {
+ if chan.amp_res {
+ (&cbs.env_bal_3_0db_f_cb, &cbs.env_bal_3_0db_t_cb)
+ } else {
+ (&cbs.env_bal_1_5db_f_cb, &cbs.env_bal_1_5db_t_cb)
+ }
+ } else {
+ if chan.amp_res {
+ (&cbs.env_3_0db_f_cb, &cbs.env_3_0db_t_cb)
+ } else {
+ (&cbs.env_1_5db_f_cb, &cbs.env_1_5db_t_cb)
+ }
+ };
+ let scale = if coupled { 2 } else { 1 };
+ for (envelope, (&df_env, &freq_res)) in chan.data_env[..chan.num_env].iter_mut().zip(chan.df_env.iter().zip(chan.freq_res.iter())) {
+ let num_env_bands = state.num_env_bands[freq_res as usize];
+ if !df_env {
+ if coupled {
+ envelope[0] = br.read(5 + (!chan.amp_res as u8))? as i8;
+ } else {
+ envelope[0] = br.read(6 + (!chan.amp_res as u8))? as i8;
+ }
+ envelope[0] *= scale;
+ let mut last = envelope[0];
+ for band_env in envelope[1..num_env_bands].iter_mut() {
+ let delta = br.read_cb(f_cb)?;
+ *band_env = last + delta * scale;
+ last = *band_env
+ }
+ } else {
+ for (i, band_env) in envelope[..num_env_bands].iter_mut().enumerate() {
+ let delta = br.read_cb(t_cb)?;
+ let last = match (freq_res, chan.last_freq_res) {
+ (true, false) => chan.last_envelope[state.high_to_low_res[i]],
+ (false, true) => chan.last_envelope[state.low_to_high_res[i]],
+ _ => chan.last_envelope[i],
+ };
+ *band_env = last + delta * scale;
+ }
+ }
+ chan.last_envelope = *envelope;
+ chan.last_freq_res = freq_res;
+ }
+ Ok(())
+}
+fn read_noise(br: &mut BitReader, chan: &mut SBRChannel, coupled: bool, cbs: &SBRCodebooks, state: &SBRState) -> DecoderResult<()> {
+ let (f_cb, t_cb) = if coupled {
+ (&cbs.env_bal_3_0db_f_cb, &cbs.noise_bal_3_0db_t_cb)
+ } else {
+ (&cbs.env_3_0db_f_cb, &cbs.noise_3_0db_t_cb)
+ };
+ let scale = if coupled { 2 } else { 1 };
+ for (noise, &df_noise) in chan.data_noise[..chan.num_noise].iter_mut().zip(chan.df_noise.iter()) {
+ if !df_noise {
+ noise[0] = (br.read(5)? as i8) * scale;
+ let mut last = noise[0];
+ for band_noise in noise[1..state.num_noise_bands].iter_mut() {
+ let delta = br.read_cb(f_cb)?;
+ *band_noise = last + scale * delta;
+ last = *band_noise;
+ }
+ } else {
+ for (band_noise, &last) in noise[..state.num_noise_bands].iter_mut().zip(chan.last_noise_env.iter()) {
+ let delta = br.read_cb(t_cb)?;
+ *band_noise = last + delta * scale;
+ }
+ }
+ chan.last_noise_env = *noise;
+ }
+ Ok(())
+}
+fn read_sinusoidal_coding(br: &mut BitReader, chan: &mut SBRChannel, state: &SBRState) -> DecoderResult<()> {
+ if !br.read_bool()? {
+ chan.add_harmonic = [false; SBR_BANDS];
+ return Ok(());
+ }
+ for el in chan.add_harmonic[..state.num_env_bands[1]].iter_mut() {
+ *el = br.read_bool()?;
+ }
+ Ok(())
+}
+fn read_extensions(br: &mut BitReader) -> DecoderResult<()> {
+ if br.read_bool()? {
+ let mut size = br.read(4)? as usize;
+ if size == 15 {
+ size += br.read(8)? as usize;
+ }
+ validate!(br.left() >= ((size * 8) as isize));
+ let end = br.tell() + size * 8;
+ while br.tell() + 7 < end {
+ let _extension_id = br.read(2)?;
+ // todo parse PS?
+ }
+ }
+ Ok(())
+}
+
+pub struct SBRCodebooks {
+ env_bal_1_5db_f_cb: Codebook<i8>,
+ env_bal_1_5db_t_cb: Codebook<i8>,
+ env_bal_3_0db_f_cb: Codebook<i8>,
+ env_bal_3_0db_t_cb: Codebook<i8>,
+ env_1_5db_f_cb: Codebook<i8>,
+ env_1_5db_t_cb: Codebook<i8>,
+ env_3_0db_f_cb: Codebook<i8>,
+ env_3_0db_t_cb: Codebook<i8>,
+ noise_bal_3_0db_t_cb: Codebook<i8>,
+ noise_3_0db_t_cb: Codebook<i8>,
+}
+
+fn map_idx12(idx: usize) -> i8 { idx as i8 - 12 }
+fn map_idx24(idx: usize) -> i8 { idx as i8 - 24 }
+fn map_idx31(idx: usize) -> i8 { idx as i8 - 31 }
+fn map_idx60(idx: usize) -> i8 { idx as i8 - 60 }
+
+impl SBRCodebooks {
+ pub fn new() -> Self {
+ let mut cbr = TableCodebookDescReader::new(ENV_BAL_1_5DB_F_BITS, ENV_BAL_1_5DB_F_LENS, map_idx24);
+ let env_bal_1_5db_f_cb = Codebook::new(&mut cbr, CodebookMode::MSB).unwrap();
+ let mut cbr = TableCodebookDescReader::new(ENV_BAL_1_5DB_T_BITS, ENV_BAL_1_5DB_T_LENS, map_idx24);
+ let env_bal_1_5db_t_cb = Codebook::new(&mut cbr, CodebookMode::MSB).unwrap();
+
+ let mut cbr = TableCodebookDescReader::new(ENV_1_5DB_F_BITS, ENV_1_5DB_F_LENS, map_idx60);
+ let env_1_5db_f_cb = Codebook::new(&mut cbr, CodebookMode::MSB).unwrap();
+ let mut cbr = TableCodebookDescReader::new(ENV_1_5DB_T_BITS, ENV_1_5DB_T_LENS, map_idx60);
+ let env_1_5db_t_cb = Codebook::new(&mut cbr, CodebookMode::MSB).unwrap();
+
+ let mut cbr = TableCodebookDescReader::new(ENV_BAL_3_0DB_F_BITS, ENV_BAL_3_0DB_F_LENS, map_idx12);
+ let env_bal_3_0db_f_cb = Codebook::new(&mut cbr, CodebookMode::MSB).unwrap();
+ let mut cbr = TableCodebookDescReader::new(ENV_BAL_3_0DB_T_BITS, ENV_BAL_3_0DB_T_LENS, map_idx12);
+ let env_bal_3_0db_t_cb = Codebook::new(&mut cbr, CodebookMode::MSB).unwrap();
+
+ let mut cbr = TableCodebookDescReader::new(ENV_3_0DB_F_BITS, ENV_3_0DB_F_LENS, map_idx31);
+ let env_3_0db_f_cb = Codebook::new(&mut cbr, CodebookMode::MSB).unwrap();
+ let mut cbr = TableCodebookDescReader::new(ENV_3_0DB_T_BITS, ENV_3_0DB_T_LENS, map_idx31);
+ let env_3_0db_t_cb = Codebook::new(&mut cbr, CodebookMode::MSB).unwrap();
+
+ let mut cbr = TableCodebookDescReader::new(NOISE_BAL_3_0DB_T_BITS, NOISE_BAL_3_0DB_T_LENS, map_idx12);
+ let noise_bal_3_0db_t_cb = Codebook::new(&mut cbr, CodebookMode::MSB).unwrap();
+ let mut cbr = TableCodebookDescReader::new(NOISE_3_0DB_T_BITS, NOISE_3_0DB_T_LENS, map_idx31);
+ let noise_3_0db_t_cb = Codebook::new(&mut cbr, CodebookMode::MSB).unwrap();
+
+ Self {
+ env_bal_1_5db_f_cb, env_bal_1_5db_t_cb,
+ env_1_5db_f_cb, env_1_5db_t_cb,
+ env_bal_3_0db_f_cb, env_bal_3_0db_t_cb,
+ env_3_0db_f_cb, env_3_0db_t_cb,
+ noise_3_0db_t_cb, noise_bal_3_0db_t_cb
+ }
+ }
+}
+
+const ENV_1_5DB_F_BITS: &[u32; 121] = &[
+ 0x7ffe7, 0x7ffe8, 0xfffd2, 0xfffd3, 0xfffd4, 0xfffd5, 0xfffd6, 0xfffd7,
+ 0xfffd8, 0x7ffda, 0xfffd9, 0xfffda, 0xfffdb, 0xfffdc, 0x7ffdb, 0xfffdd,
+ 0x7ffdc, 0x7ffdd, 0xfffde, 0x3ffe4, 0xfffdf, 0xfffe0, 0xfffe1, 0x7ffde,
+ 0xfffe2, 0xfffe3, 0xfffe4, 0x7ffdf, 0xfffe5, 0x7ffe0, 0x3ffe8, 0x7ffe1,
+ 0x3ffe0, 0x3ffe9, 0x1ffef, 0x3ffe5, 0x1ffec, 0x1ffed, 0x1ffee, 0x0fff4,
+ 0x0fff3, 0x0fff0, 0x07ff7, 0x07ff6, 0x03ffa, 0x01ffa, 0x01ff9, 0x00ffa,
+ 0x00ff8, 0x007f9, 0x003fb, 0x001fc, 0x001fa, 0x000fb, 0x0007c, 0x0003c,
+ 0x0001c, 0x0000c, 0x00005, 0x00001, 0x00000, 0x00004, 0x0000d, 0x0001d,
+ 0x0003d, 0x000fa, 0x000fc, 0x001fb, 0x003fa, 0x007f8, 0x007fa, 0x007fb,
+ 0x00ff9, 0x00ffb, 0x01ff8, 0x01ffb, 0x03ff8, 0x03ff9, 0x0fff1, 0x0fff2,
+ 0x1ffea, 0x1ffeb, 0x3ffe1, 0x3ffe2, 0x3ffea, 0x3ffe3, 0x3ffe6, 0x3ffe7,
+ 0x3ffeb, 0xfffe6, 0x7ffe2, 0xfffe7, 0xfffe8, 0xfffe9, 0xfffea, 0xfffeb,
+ 0xfffec, 0x7ffe3, 0xfffed, 0xfffee, 0xfffef, 0xffff0, 0x7ffe4, 0xffff1,
+ 0x3ffec, 0xffff2, 0xffff3, 0x7ffe5, 0x7ffe6, 0xffff4, 0xffff5, 0xffff6,
+ 0xffff7, 0xffff8, 0xffff9, 0xffffa, 0xffffb, 0xffffc, 0xffffd, 0xffffe,
+ 0xfffff
+];
+const ENV_1_5DB_F_LENS: &[u8; 121] = &[
+ 19, 19, 20, 20, 20, 20, 20, 20,
+ 20, 19, 20, 20, 20, 20, 19, 20,
+ 19, 19, 20, 18, 20, 20, 20, 19,
+ 20, 20, 20, 19, 20, 19, 18, 19,
+ 18, 18, 17, 18, 17, 17, 17, 16,
+ 16, 16, 15, 15, 14, 13, 13, 12,
+ 12, 11, 10, 9, 9, 8, 7, 6,
+ 5, 4, 3, 2, 2, 3, 4, 5,
+ 6, 8, 8, 9, 10, 11, 11, 11,
+ 12, 12, 13, 13, 14, 14, 16, 16,
+ 17, 17, 18, 18, 18, 18, 18, 18,
+ 18, 20, 19, 20, 20, 20, 20, 20,
+ 20, 19, 20, 20, 20, 20, 19, 20,
+ 18, 20, 20, 19, 19, 20, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20,
+ 20
+];
+const ENV_1_5DB_T_BITS: &[u32; 121] = &[
+ 0x3ffd6, 0x3ffd7, 0x3ffd8, 0x3ffd9, 0x3ffda, 0x3ffdb, 0x7ffb8, 0x7ffb9,
+ 0x7ffba, 0x7ffbb, 0x7ffbc, 0x7ffbd, 0x7ffbe, 0x7ffbf, 0x7ffc0, 0x7ffc1,
+ 0x7ffc2, 0x7ffc3, 0x7ffc4, 0x7ffc5, 0x7ffc6, 0x7ffc7, 0x7ffc8, 0x7ffc9,
+ 0x7ffca, 0x7ffcb, 0x7ffcc, 0x7ffcd, 0x7ffce, 0x7ffcf, 0x7ffd0, 0x7ffd1,
+ 0x7ffd2, 0x7ffd3, 0x1ffe6, 0x3ffd4, 0x0fff0, 0x1ffe9, 0x3ffd5, 0x1ffe7,
+ 0x0fff1, 0x0ffec, 0x0ffed, 0x0ffee, 0x07ff4, 0x03ff9, 0x03ff7, 0x01ffa,
+ 0x01ff9, 0x00ffb, 0x007fc, 0x003fc, 0x001fd, 0x000fd, 0x0007d, 0x0003d,
+ 0x0001d, 0x0000d, 0x00005, 0x00001, 0x00000, 0x00004, 0x0000c, 0x0001c,
+ 0x0003c, 0x0007c, 0x000fc, 0x001fc, 0x003fd, 0x00ffa, 0x01ff8, 0x03ff6,
+ 0x03ff8, 0x07ff5, 0x0ffef, 0x1ffe8, 0x0fff2, 0x7ffd4, 0x7ffd5, 0x7ffd6,
+ 0x7ffd7, 0x7ffd8, 0x7ffd9, 0x7ffda, 0x7ffdb, 0x7ffdc, 0x7ffdd, 0x7ffde,
+ 0x7ffdf, 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
+];
+const ENV_1_5DB_T_LENS: &[u8; 121] = &[
+ 18, 18, 18, 18, 18, 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, 17, 18, 16, 17, 18, 17,
+ 16, 16, 16, 16, 15, 14, 14, 13,
+ 13, 12, 11, 10, 9, 8, 7, 6,
+ 5, 4, 3, 2, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10, 12, 13, 14,
+ 14, 15, 16, 17, 16, 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,
+ 19
+];
+
+const ENV_BAL_1_5DB_F_BITS: &[u32; 49] = &[
+ 0x3ffe2, 0x3ffe3, 0x3ffe4, 0x3ffe5, 0x3ffe6, 0x3ffe7, 0x3ffe8, 0x3ffe9,
+ 0x3ffea, 0x3ffeb, 0x3ffec, 0x3ffed, 0x3ffee, 0x3ffef, 0x3fff0, 0x0fff7,
+ 0x1fff0, 0x03ffc, 0x007fe, 0x007fc, 0x000fe, 0x0007e, 0x0000e, 0x00002,
+ 0x00000, 0x00006, 0x0001e, 0x0003e, 0x001fe, 0x007fd, 0x00ffe, 0x07ffa,
+ 0x0fff6, 0x3fff1, 0x3fff2, 0x3fff3, 0x3fff4, 0x3fff5, 0x3fff6, 0x3fff7,
+ 0x3fff8, 0x3fff9, 0x3fffa, 0x3fffb, 0x3fffc, 0x3fffd, 0x3fffe, 0x7fffe,
+ 0x7ffff
+];
+const ENV_BAL_1_5DB_F_LENS: &[u8; 49] = &[
+ 18, 18, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 18, 18, 18, 18, 16,
+ 17, 14, 11, 11, 8, 7, 4, 2,
+ 1, 3, 5, 6, 9, 11, 12, 15,
+ 16, 18, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 18, 18, 18, 18, 19,
+ 19
+];
+const ENV_BAL_1_5DB_T_BITS: &[u32; 49] = &[
+ 0x0ffe4, 0x0ffe5, 0x0ffe6, 0x0ffe7, 0x0ffe8, 0x0ffe9, 0x0ffea, 0x0ffeb,
+ 0x0ffec, 0x0ffed, 0x0ffee, 0x0ffef, 0x0fff0, 0x0fff1, 0x0fff2, 0x0fff3,
+ 0x0fff4, 0x0ffe2, 0x00ffc, 0x007fc, 0x001fe, 0x0007e, 0x0001e, 0x00006,
+ 0x00000, 0x00002, 0x0000e, 0x0003e, 0x000fe, 0x007fd, 0x00ffd, 0x07ff0,
+ 0x0ffe3, 0x0fff5, 0x0fff6, 0x0fff7, 0x0fff8, 0x0fff9, 0x0fffa, 0x1fff6,
+ 0x1fff7, 0x1fff8, 0x1fff9, 0x1fffa, 0x1fffb, 0x1fffc, 0x1fffd, 0x1fffe,
+ 0x1ffff
+];
+const ENV_BAL_1_5DB_T_LENS: &[u8; 49] = &[
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 12, 11, 9, 7, 5, 3,
+ 1, 2, 4, 6, 8, 11, 12, 15,
+ 16, 16, 16, 16, 16, 16, 16, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17
+];
+
+const ENV_3_0DB_F_BITS: &[u32; 63] = &[
+ 0xffff0, 0xffff1, 0xffff2, 0xffff3, 0xffff4, 0xffff5, 0xffff6, 0x3fff3,
+ 0x7fff5, 0x7ffee, 0x7ffef, 0x7fff6, 0x3fff4, 0x3fff2, 0xffff7, 0x7fff0,
+ 0x1fff5, 0x3fff0, 0x1fff4, 0x0fff7, 0x0fff6, 0x07ff8, 0x03ffb, 0x00ffd,
+ 0x007fd, 0x003fd, 0x001fd, 0x000fd, 0x0003e, 0x0000e, 0x00002, 0x00000,
+ 0x00006, 0x0001e, 0x000fc, 0x001fc, 0x003fc, 0x007fc, 0x00ffc, 0x01ffc,
+ 0x03ffa, 0x07ff9, 0x07ffa, 0x0fff8, 0x0fff9, 0x1fff6, 0x1fff7, 0x3fff5,
+ 0x3fff6, 0x3fff1, 0xffff8, 0x7fff1, 0x7fff2, 0x7fff3, 0xffff9, 0x7fff7,
+ 0x7fff4, 0xffffa, 0xffffb, 0xffffc, 0xffffd, 0xffffe, 0xfffff
+];
+const ENV_3_0DB_F_LENS: &[u8; 63] = &[
+ 20, 20, 20, 20, 20, 20, 20, 18,
+ 19, 19, 19, 19, 18, 18, 20, 19,
+ 17, 18, 17, 16, 16, 15, 14, 12,
+ 11, 10, 9, 8, 6, 4, 2, 1,
+ 3, 5, 8, 9, 10, 11, 12, 13,
+ 14, 15, 15, 16, 16, 17, 17, 18,
+ 18, 18, 20, 19, 19, 19, 20, 19,
+ 19, 20, 20, 20, 20, 20, 20
+];
+const ENV_3_0DB_T_BITS: &[u32; 63] = &[
+ 0x3ffed, 0x3ffee, 0x7ffde, 0x7ffdf, 0x7ffe0, 0x7ffe1, 0x7ffe2, 0x7ffe3,
+ 0x7ffe4, 0x7ffe5, 0x7ffe6, 0x7ffe7, 0x7ffe8, 0x7ffe9, 0x7ffea, 0x7ffeb,
+ 0x7ffec, 0x1fff4, 0x0fff7, 0x0fff9, 0x0fff8, 0x03ffb, 0x03ffa, 0x03ff8,
+ 0x01ffa, 0x00ffc, 0x007fc, 0x000fe, 0x0003e, 0x0000e, 0x00002, 0x00000,
+ 0x00006, 0x0001e, 0x0007e, 0x001fe, 0x007fd, 0x01ffb, 0x03ff9, 0x03ffc,
+ 0x07ffa, 0x0fff6, 0x1fff5, 0x3ffec, 0x7ffed, 0x7ffee, 0x7ffef, 0x7fff0,
+ 0x7fff1, 0x7fff2, 0x7fff3, 0x7fff4, 0x7fff5, 0x7fff6, 0x7fff7, 0x7fff8,
+ 0x7fff9, 0x7fffa, 0x7fffb, 0x7fffc, 0x7fffd, 0x7fffe, 0x7ffff
+];
+const ENV_3_0DB_T_LENS: &[u8; 63] = &[
+ 18, 18, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 17, 16, 16, 16, 14, 14, 14,
+ 13, 12, 11, 8, 6, 4, 2, 1,
+ 3, 5, 7, 9, 11, 13, 14, 14,
+ 15, 16, 17, 18, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19
+];
+
+const ENV_BAL_3_0DB_F_BITS: &[u16; 25] = &[
+ 0x1ff7, 0x1ff8, 0x1ff9, 0x1ffa, 0x1ffb, 0x3ff8, 0x3ff9, 0x07fc,
+ 0x00fe, 0x007e, 0x000e, 0x0002, 0x0000, 0x0006, 0x001e, 0x003e,
+ 0x01fe, 0x0ffa, 0x1ff6, 0x3ffa, 0x3ffb, 0x3ffc, 0x3ffd, 0x3ffe,
+ 0x3fff
+];
+const ENV_BAL_3_0DB_F_LENS: &[u8; 25] = &[
+ 13, 13, 13, 13, 13, 14, 14, 11,
+ 8, 7, 4, 2, 1, 3, 5, 6,
+ 9, 12, 13, 14, 14, 14, 14, 14,
+ 14
+];
+const ENV_BAL_3_0DB_T_BITS: &[u16; 25] = &[
+ 0x1ff2, 0x1ff3, 0x1ff4, 0x1ff5, 0x1ff6, 0x1ff7, 0x1ff8, 0x0ff8,
+ 0x00fe, 0x007e, 0x000e, 0x0006, 0x0000, 0x0002, 0x001e, 0x003e,
+ 0x01fe, 0x1ff9, 0x1ffa, 0x1ffb, 0x1ffc, 0x1ffd, 0x1ffe, 0x3ffe,
+ 0x3fff
+];
+const ENV_BAL_3_0DB_T_LENS: &[u8; 25] = &[
+ 13, 13, 13, 13, 13, 13, 13, 12,
+ 8, 7, 4, 3, 1, 2, 5, 6,
+ 9, 13, 13, 13, 13, 13, 13, 14,
+ 14
+];
+
+const NOISE_3_0DB_T_BITS: &[u16; 63] = &[
+ 0x1fce, 0x1fcf, 0x1fd0, 0x1fd1, 0x1fd2, 0x1fd3, 0x1fd4, 0x1fd5,
+ 0x1fd6, 0x1fd7, 0x1fd8, 0x1fd9, 0x1fda, 0x1fdb, 0x1fdc, 0x1fdd,
+ 0x1fde, 0x1fdf, 0x1fe0, 0x1fe1, 0x1fe2, 0x1fe3, 0x1fe4, 0x1fe5,
+ 0x1fe6, 0x1fe7, 0x07f2, 0x00fd, 0x003e, 0x000e, 0x0006, 0x0000,
+ 0x0002, 0x001e, 0x00fc, 0x03f8, 0x1fcc, 0x1fe8, 0x1fe9, 0x1fea,
+ 0x1feb, 0x1fec, 0x1fcd, 0x1fed, 0x1fee, 0x1fef, 0x1ff0, 0x1ff1,
+ 0x1ff2, 0x1ff3, 0x1ff4, 0x1ff5, 0x1ff6, 0x1ff7, 0x1ff8, 0x1ff9,
+ 0x1ffa, 0x1ffb, 0x1ffc, 0x1ffd, 0x1ffe, 0x3ffe, 0x3fff
+];
+const NOISE_3_0DB_T_LENS: &[u8; 63] = &[
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 11, 8, 6, 4, 3, 1,
+ 2, 5, 8, 10, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 14, 14
+];
+const NOISE_BAL_3_0DB_T_BITS: &[u8; 25] = &[
+ 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3,
+ 0xf4, 0xf5, 0x1c, 0x02, 0x00, 0x06, 0x3a, 0xf6,
+ 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe,
+ 0xff
+];
+const NOISE_BAL_3_0DB_T_LENS: &[u8; 25] = &[
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 5, 2, 1, 3, 6, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8
+];
--- /dev/null
+pub use nihav_codec_support::dsp::fft::*;
+pub use nihav_codec_support::dsp::mdct::*;
+
+pub struct SBRDSP {
+ imdct: IMDCT,
+ tmp0: [f32; 64],
+ tmp1: [f32; 64],
+ tmp2: [f32; 64],
+ tmp3: [f32; 64],
+}
+
+impl SBRDSP {
+ pub fn new() -> Self {
+ Self {
+ imdct: IMDCT::new(128, false),
+ tmp0: [0.0; 64],
+ tmp1: [0.0; 64],
+ tmp2: [0.0; 64],
+ tmp3: [0.0; 64],
+ }
+ }
+}
+
+#[derive(Clone)]
+pub struct SBRAnalysis {
+ hist: [f32; 320],
+ pos: usize,
+}
+
+impl SBRAnalysis {
+ pub fn new() -> Self {
+ Self {
+ hist: [0.0; 320],
+ pos: 0,
+ }
+ }
+ pub fn analysis(&mut self, dsp: &mut SBRDSP, samples: &[f32], dst: &mut [FFTComplex; 64]) {
+ self.pos += self.hist.len() - 32;
+ if self.pos >= self.hist.len() {
+ self.pos -= self.hist.len();
+ }
+ for (dst, &src) in self.hist[self.pos..][..32].iter_mut().zip(samples.iter().rev()) {
+ *dst = src;
+ }
+
+ let sum = &mut dsp.tmp0;
+ *sum = [0.0; 64];
+ for (n, dst) in sum.iter_mut().enumerate() {
+ *dst = 0.0;
+ for j in 0..5 {
+ *dst += self.hist[(self.pos + n + j * 64) % self.hist.len()] * SBR_WINDOW[(n + j * 64) * 2];
+ }
+ }
+
+ let src = &mut dsp.tmp1;
+
+ src[0] = sum[0];
+ src[1] = sum[1];
+ for k in (1..31).step_by(2) {
+ src[k * 2] = -sum[64 - k];
+ src[k * 2 + 1] = sum[k + 1];
+ src[k * 2 + 2] = -sum[63 - k];
+ src[k * 2 + 3] = sum[k + 2];
+ }
+ src[62] = -sum[33];
+ src[63] = sum[32];
+
+ let out = &mut dsp.tmp2;
+ dsp.imdct.imdct_half(src, out);
+
+ *dst = [FFTC_ZERO; 64];
+ for (k, dst) in dst[..32].iter_mut().enumerate() {
+ dst.re = -out[63 - k];
+ dst.im = out[k];
+ }
+ }
+}
+
+#[derive(Clone)]
+pub struct SBRSynthesis {
+ hist: [f32; 1280],
+ pos: usize,
+}
+
+impl SBRSynthesis {
+ pub fn new() -> Self {
+ Self {
+ hist: [0.0; 1280],
+ pos: 0,
+ }
+ }
+ pub fn synthesis(&mut self, dsp: &mut SBRDSP, src: &[FFTComplex; 64], dst: &mut [f32]) {
+ self.pos += self.hist.len() - 128;
+ if self.pos >= self.hist.len() {
+ self.pos -= self.hist.len();
+ }
+ let re = &mut dsp.tmp0;
+ let im = &mut dsp.tmp1;
+ for ((re, im), src) in re.iter_mut().zip(im.iter_mut()).zip(src.iter()) {
+ *re = src.re / 32.0;
+ *im = src.im / 32.0;
+ }
+ for pair in im.chunks_mut(2) {
+ pair[1] = -pair[1];
+ }
+ let out0 = &mut dsp.tmp2;
+ let out1 = &mut dsp.tmp3;
+ dsp.imdct.imdct_half(re, out0);
+ dsp.imdct.imdct_half(im, out1);
+
+ for (k, (&a, &b)) in out1.iter().zip(out0.iter().rev()).enumerate() {
+ self.hist[self.pos..][k] = a - b;
+ self.hist[self.pos..][127 - k] = a + b;
+ }
+
+ for (k, dst) in dst[..64].iter_mut().enumerate() {
+ *dst = 0.0;
+ for n in 0..5 {
+ *dst += self.hist[(self.pos + 256 * n + k) % self.hist.len()] * SBR_WINDOW[128 * n + k];
+ *dst += self.hist[(self.pos + 256 * n + k + 192) % self.hist.len()] * SBR_WINDOW[128 * n + k + 64];
+ }
+ }
+ }
+}
+
+/*#[derive(Clone)]
+pub struct SBRSynthesisDownsampled {
+ hist: [f32; 640],
+ pos: usize,
+}
+
+impl SBRSynthesisDownsampled {
+ pub fn new() -> Self {
+ Self {
+ hist: [0.0; 640],
+ pos: 0,
+ }
+ }
+ pub fn synthesis(&mut self, dsp: &mut SBRDSP, src: &[FFTComplex; 64], dst: &mut [f32]) {
+ self.pos += self.hist.len() - 64;
+ if self.pos >= self.hist.len() {
+ self.pos -= self.hist.len();
+ }
+
+ let (p0, p1) = dsp.tmp0.split_at_mut(32);
+ let out = &mut dsp.tmp1;
+ for (n, (dst0, dst1)) in p0.iter_mut().zip(p1.iter_mut()).enumerate() {
+ *dst0 = -src[n].re / 32.0;
+ *dst1 = src[31 - n].im / 32.0;
+ }
+ dsp.imdct.imdct_half(&dsp.tmp0, out);
+ for (k, pair) in out.chunks(2).rev().enumerate() {
+ self.hist[self.pos..][k] = pair[1];
+ self.hist[self.pos..][63 - k] = -pair[0];
+ }
+
+ for (k, dst) in dst[..32].iter_mut().enumerate() {
+ *dst = 0.0;
+ for n in 0..5 {
+ *dst += self.hist[(self.pos + 128 * n + k) % self.hist.len()] * SBR_WINDOW[128 * n + k];
+ *dst += self.hist[(self.pos + 128 * n + k + 96) % self.hist.len()] * SBR_WINDOW[128 * n + k + 64];
+ }
+ }
+ }
+}*/
+
+const SBR_WINDOW: [f32; 640] = [
+ 0.0, -0.00055252865047, -0.00056176925738, -0.00049475180896,
+ -0.00048752279712, -0.00048937912498, -0.00050407143497, -0.00052265642972,
+ -0.00054665656337, -0.00056778025613, -0.00058709304852, -0.00061327473938,
+ -0.00063124935319, -0.00065403333621, -0.00067776907764, -0.00069416146273,
+ -0.00071577364744, -0.00072550431222, -0.00074409418541, -0.00074905980532,
+ -0.0007681371927, -0.00077248485949, -0.00078343322877, -0.00077798694927,
+ -0.000780366471, -0.00078014496257, -0.0007757977331, -0.00076307935757,
+ -0.00075300014201, -0.00073193571525, -0.00072153919876, -0.00069179375372,
+ -0.00066504150893, -0.00063415949025, -0.0005946118933, -0.00055645763906,
+ -0.00051455722108, -0.00046063254803, -0.00040951214522, -0.00035011758756,
+ -0.00028969811748, -0.0002098337344, -0.00014463809349, -0.00006173344072,
+ 0.00001349497418, 0.00010943831274, 0.00020430170688, 0.00029495311041,
+ 0.0004026540216, 0.00051073884952, 0.00062393761391, 0.00074580258865,
+ 0.00086084433262, 0.00098859883015, 0.00112501551307, 0.00125778846475,
+ 0.00139024948272, 0.00154432198471, 0.00168680832531, 0.00183482654224,
+ 0.00198411407369, 0.00214615835557, 0.00230172547746, 0.00246256169126,
+ 0.00262017586902, 0.00278704643465, 0.00294694477165, 0.00311254206525,
+ 0.00327396134847, 0.00344188741828, 0.00360082681231, 0.00376039229104,
+ 0.00392074323703, 0.00408197531935, 0.0042264269227, 0.00437307196781,
+ 0.00452098527825, 0.00466064606118, 0.00479325608498, 0.00491376035745,
+ 0.00503930226013, 0.00514073539032, 0.00524611661324, 0.00534716811982,
+ 0.00541967759307, 0.00548760401507, 0.00554757145088, 0.00559380230045,
+ 0.00562206432097, 0.00564551969164, 0.00563891995151, 0.00562661141932,
+ 0.0055917128663, 0.005540436394, 0.0054753783077, 0.0053838975897,
+ 0.00527157587272, 0.00513822754514, 0.00498396877629, 0.004810946906,
+ 0.00460395301471, 0.00438018617447, 0.0041251642327, 0.00384564081246,
+ 0.00354012465507, 0.00320918858098, 0.00284467578623, 0.00245085400321,
+ 0.0020274176185, 0.00157846825768, 0.00109023290512, 0.0005832264248,
+ 0.00002760451905, -0.00054642808664, -0.00115681355227, -0.00180394725893,
+ -0.00248267236449, -0.003193377839, -0.00394011240522, -0.004722259624,
+ -0.00553372111088, -0.00637922932685, -0.00726158168517, -0.00817982333726,
+ -0.00913253296085, -0.01011502154986, -0.01113155480321, -0.01218499959508,
+ 0.01327182200351, 0.01439046660792, 0.01554055533423, 0.01673247129989,
+ 0.01794333813443, 0.01918724313698, 0.02045317933555, 0.02174675502535,
+ 0.02306801692862, 0.02441609920285, 0.02578758475467, 0.02718594296329,
+ 0.02860721736385, 0.03005026574279, 0.03150176087389, 0.03297540810337,
+ 0.03446209487686, 0.03596975605542, 0.03748128504252, 0.03900536794745,
+ 0.04053491705584, 0.04206490946367, 0.04360975421304, 0.04514884056413,
+ 0.04668430272642, 0.04821657200672, 0.04973857556014, 0.05125561555216,
+ 0.05276307465207, 0.05424527683589, 0.05571736482138, 0.05716164501299,
+ 0.0585915683626, 0.05998374801761, 0.06134551717207, 0.06268578081172,
+ 0.06397158980681, 0.0652247106438, 0.06643675122104, 0.06760759851228,
+ 0.06870438283512, 0.06976302447127, 0.07076287107266, 0.07170026731102,
+ 0.07256825833083, 0.07336202550803, 0.07410036424342, 0.07474525581194,
+ 0.07531373362019, 0.07580083586584, 0.07619924793396, 0.07649921704119,
+ 0.07670934904245, 0.07681739756964, 0.07682300113923, 0.07672049241746,
+ 0.07650507183194, 0.07617483218536, 0.07573057565061, 0.0751576255287,
+ 0.07446643947564, 0.0736406005762, 0.07267746427299, 0.07158263647903,
+ 0.07035330735093, 0.06896640131951, 0.06745250215166, 0.06576906686508,
+ 0.06394448059633, 0.06196027790387, 0.0598166570809, 0.05751526919867,
+ 0.05504600343009, 0.05240938217366, 0.04959786763445, 0.04663033051701,
+ 0.04347687821958, 0.04014582784127, 0.03664181168133, 0.03295839306691,
+ 0.02908240060125, 0.02503075618909, 0.02079970728622, 0.01637012582228,
+ 0.01176238327857, 0.00696368621617, 0.00197656014503, -0.00320868968304,
+ -0.00857117491366, -0.01412888273558, -0.01988341292573, -0.02582272888064,
+ -0.03195312745332, -0.03827765720822, -0.04478068215856, -0.05148041767934,
+ -0.05837053268336, -0.06544098531359, -0.07269433008129, -0.08013729344279,
+ -0.08775475365593, -0.09555333528914, -0.10353295311463, -0.1116826931773,
+ -0.120007798468, -0.12850028503878, -0.13715517611934, -0.1459766491187,
+ -0.15496070710605, -0.16409588556669, -0.17338081721706, -0.18281725485142,
+ -0.19239667457267, -0.20212501768103, -0.21197358538056, -0.22196526964149,
+ -0.23206908706791, -0.24230168845974, -0.25264803095722, -0.26310532994603,
+ -0.27366340405625, -0.28432141891085, -0.29507167170646, -0.30590985751916,
+ -0.31682789136456, -0.32781137272105, -0.33887226938665, -0.3499914122931,
+ 0.36115899031355, 0.37237955463061, 0.38363500139043, 0.39492117615675,
+ 0.40623176767625, 0.41756968968409, 0.42891199207373, 0.44025537543665,
+ 0.45159965356824, 0.46293080852757, 0.47424532146115, 0.48552530911099,
+ 0.49677082545707, 0.50798175000434, 0.51912349702391, 0.53022408956855,
+ 0.54125534487322, 0.55220512585061, 0.5630789140137, 0.57385241316923,
+ 0.58454032354679, 0.59511230862496, 0.6055783538918, 0.61591099320291,
+ 0.62612426956055, 0.63619801077286, 0.64612696959461, 0.65590163024671,
+ 0.66551398801627, 0.67496631901712, 0.68423532934598, 0.69332823767032,
+ 0.70223887193539, 0.71094104263095, 0.71944626349561, 0.72774489002994,
+ 0.73582117582769, 0.74368278636488, 0.75131374561237, 0.75870807608242,
+ 0.76586748650939, 0.77277808813327, 0.77942875190216, 0.7858353120392,
+ 0.79197358416424, 0.797846641377, 0.80344857518505, 0.80876950044491,
+ 0.81381912706217, 0.81857760046468, 0.82304198905409, 0.8272275347336,
+ 0.8311038457152, 0.83469373618402, 0.83797173378865, 0.84095413924722,
+ 0.84362382812005, 0.84598184698206, 0.84803157770763, 0.84978051984268,
+ 0.85119715249343, 0.85230470352147, 0.85310209497017, 0.85357205739107,
+ 0.85373856005937, 0.85357205739107, 0.85310209497017, 0.85230470352147,
+ 0.85119715249343, 0.84978051984268, 0.84803157770763, 0.84598184698206,
+ 0.84362382812005, 0.84095413924722, 0.83797173378865, 0.83469373618402,
+ 0.8311038457152, 0.8272275347336, 0.82304198905409, 0.81857760046468,
+ 0.81381912706217, 0.80876950044491, 0.80344857518505, 0.797846641377,
+ 0.79197358416424, 0.7858353120392, 0.77942875190216, 0.77277808813327,
+ 0.76586748650939, 0.75870807608242, 0.75131374561237, 0.74368278636488,
+ 0.73582117582769, 0.72774489002994, 0.71944626349561, 0.71094104263095,
+ 0.70223887193539, 0.69332823767032, 0.68423532934598, 0.67496631901712,
+ 0.66551398801627, 0.65590163024671, 0.64612696959461, 0.63619801077286,
+ 0.62612426956055, 0.61591099320291, 0.6055783538918, 0.59511230862496,
+ 0.58454032354679, 0.57385241316923, 0.5630789140137, 0.55220512585061,
+ 0.54125534487322, 0.53022408956855, 0.51912349702391, 0.50798175000434,
+ 0.49677082545707, 0.48552530911099, 0.47424532146115, 0.46293080852757,
+ 0.45159965356824, 0.44025537543665, 0.42891199207373, 0.41756968968409,
+ 0.40623176767625, 0.39492117615675, 0.38363500139043, 0.37237955463061,
+ -0.36115899031355, -0.3499914122931, -0.33887226938665, -0.32781137272105,
+ -0.31682789136456, -0.30590985751916, -0.29507167170646, -0.28432141891085,
+ -0.27366340405625, -0.26310532994603, -0.25264803095722, -0.24230168845974,
+ -0.23206908706791, -0.22196526964149, -0.21197358538056, -0.20212501768103,
+ -0.19239667457267, -0.18281725485142, -0.17338081721706, -0.16409588556669,
+ -0.15496070710605, -0.1459766491187, -0.13715517611934, -0.12850028503878,
+ -0.120007798468, -0.1116826931773, -0.10353295311463, -0.09555333528914,
+ -0.08775475365593, -0.08013729344279, -0.07269433008129, -0.06544098531359,
+ -0.05837053268336, -0.05148041767934, -0.04478068215856, -0.03827765720822,
+ -0.03195312745332, -0.02582272888064, -0.01988341292573, -0.01412888273558,
+ -0.00857117491366, -0.00320868968304, 0.00197656014503, 0.00696368621617,
+ 0.01176238327857, 0.01637012582228, 0.02079970728622, 0.02503075618909,
+ 0.02908240060125, 0.03295839306691, 0.03664181168133, 0.04014582784127,
+ 0.04347687821958, 0.04663033051701, 0.04959786763445, 0.05240938217366,
+ 0.05504600343009, 0.05751526919867, 0.0598166570809, 0.06196027790387,
+ 0.06394448059633, 0.06576906686508, 0.06745250215166, 0.06896640131951,
+ 0.07035330735093, 0.07158263647903, 0.07267746427299, 0.0736406005762,
+ 0.07446643947564, 0.0751576255287, 0.07573057565061, 0.07617483218536,
+ 0.07650507183194, 0.07672049241746, 0.07682300113923, 0.07681739756964,
+ 0.07670934904245, 0.07649921704119, 0.07619924793396, 0.07580083586584,
+ 0.07531373362019, 0.07474525581194, 0.07410036424342, 0.07336202550803,
+ 0.07256825833083, 0.07170026731102, 0.07076287107266, 0.06976302447127,
+ 0.06870438283512, 0.06760759851228, 0.06643675122104, 0.0652247106438,
+ 0.06397158980681, 0.06268578081172, 0.06134551717207, 0.05998374801761,
+ 0.0585915683626, 0.05716164501299, 0.05571736482138, 0.05424527683589,
+ 0.05276307465207, 0.05125561555216, 0.04973857556014, 0.04821657200672,
+ 0.04668430272642, 0.04514884056413, 0.04360975421304, 0.04206490946367,
+ 0.04053491705584, 0.03900536794745, 0.03748128504252, 0.03596975605542,
+ 0.03446209487686, 0.03297540810337, 0.03150176087389, 0.03005026574279,
+ 0.02860721736385, 0.02718594296329, 0.02578758475467, 0.02441609920285,
+ 0.02306801692862, 0.02174675502535, 0.02045317933555, 0.01918724313698,
+ 0.01794333813443, 0.01673247129989, 0.01554055533423, 0.01439046660792,
+ -0.01327182200351, -0.01218499959508, -0.01113155480321, -0.01011502154986,
+ -0.00913253296085, -0.00817982333726, -0.00726158168517, -0.00637922932685,
+ -0.00553372111088, -0.004722259624, -0.00394011240522, -0.003193377839,
+ -0.00248267236449, -0.00180394725893, -0.00115681355227, -0.00054642808664,
+ 0.00002760451905, 0.0005832264248, 0.00109023290512, 0.00157846825768,
+ 0.0020274176185, 0.00245085400321, 0.00284467578623, 0.00320918858098,
+ 0.00354012465507, 0.00384564081246, 0.0041251642327, 0.00438018617447,
+ 0.00460395301471, 0.004810946906, 0.00498396877629, 0.00513822754514,
+ 0.00527157587272, 0.0053838975897, 0.0054753783077, 0.005540436394,
+ 0.0055917128663, 0.00562661141932, 0.00563891995151, 0.00564551969164,
+ 0.00562206432097, 0.00559380230045, 0.00554757145088, 0.00548760401507,
+ 0.00541967759307, 0.00534716811982, 0.00524611661324, 0.00514073539032,
+ 0.00503930226013, 0.00491376035745, 0.00479325608498, 0.00466064606118,
+ 0.00452098527825, 0.00437307196781, 0.0042264269227, 0.00408197531935,
+ 0.00392074323703, 0.00376039229104, 0.00360082681231, 0.00344188741828,
+ 0.00327396134847, 0.00311254206525, 0.00294694477165, 0.00278704643465,
+ 0.00262017586902, 0.00246256169126, 0.00230172547746, 0.00214615835557,
+ 0.00198411407369, 0.00183482654224, 0.00168680832531, 0.00154432198471,
+ 0.00139024948272, 0.00125778846475, 0.00112501551307, 0.00098859883015,
+ 0.00086084433262, 0.00074580258865, 0.00062393761391, 0.00051073884952,
+ 0.0004026540216, 0.00029495311041, 0.00020430170688, 0.00010943831274,
+ 0.00001349497418, -0.00006173344072, -0.00014463809349, -0.0002098337344,
+ -0.00028969811748, -0.00035011758756, -0.00040951214522, -0.00046063254803,
+ -0.00051455722108, -0.00055645763906, -0.0005946118933, -0.00063415949025,
+ -0.00066504150893, -0.00069179375372, -0.00072153919876, -0.00073193571525,
+ -0.00075300014201, -0.00076307935757, -0.0007757977331, -0.00078014496257,
+ -0.000780366471, -0.00077798694927, -0.00078343322877, -0.00077248485949,
+ -0.0007681371927, -0.00074905980532, -0.00074409418541, -0.00072550431222,
+ -0.00071577364744, -0.00069416146273, -0.00067776907764, -0.00065403333621,
+ -0.00063124935319, -0.00061327473938, -0.00058709304852, -0.00056778025613,
+ -0.00054665656337, -0.00052265642972, -0.00050407143497, -0.00048937912498,
+ -0.00048752279712, -0.00049475180896, -0.00056176925738, -0.00055252865047
+];
--- /dev/null
+use nihav_core::codecs::{DecoderResult, DecoderError};
+use nihav_core::io::bitreader::*;
+
+mod bs;
+mod dsp;
+mod synth;
+
+pub use bs::{SBRCodebooks, sbr_read_sce, sbr_read_cpe};
+pub use dsp::SBRDSP;
+pub use synth::SBRChannel;
+
+pub const NUM_ENVELOPES: usize = 8;
+pub const NUM_PATCHES: usize = 5;
+pub const SBR_BANDS: usize = 64;
+pub const QMF_DELAY: usize = 8;
+pub const HF_ADJ: usize = 2;
+pub const MAX_SLOTS: usize = 16;
+
+#[derive(Clone, Copy, Debug)]
+pub struct SBRHeader {
+ pub amp_res: bool,
+ start_freq: usize,
+ stop_freq: usize,
+ xover_band: usize,
+ freq_scale: u8,
+ alter_scale: bool,
+ noise_bands: u8,
+ limiter_bands: u8,
+ limiter_gains: u8,
+ interpol_freq: bool,
+ smoothing_mode: bool,
+}
+
+impl SBRHeader {
+ pub fn new() -> Self {
+ let mut obj: Self = unsafe { std::mem::zeroed() };
+ obj.reset();
+ obj
+ }
+ fn reset(&mut self) {
+ self.freq_scale = 2;
+ self.alter_scale = true;
+ self.noise_bands = 2;
+ self.limiter_bands = 2;
+ self.limiter_gains = 2;
+ self.interpol_freq = true;
+ self.smoothing_mode = true;
+ }
+
+ pub fn read(br: &mut BitReader) -> DecoderResult<Self> {
+ let mut sbrh = Self::new();
+ sbrh.reset();
+ sbrh.amp_res = br.read_bool()?;
+ sbrh.start_freq = br.read(4)? as usize;
+ sbrh.stop_freq = br.read(4)? as usize;
+ sbrh.xover_band = br.read(3)? as usize;
+ br.skip(2)?;
+ let header_extra_1 = br.read_bool()?;
+ let header_extra_2 = br.read_bool()?;
+ if header_extra_1 {
+ sbrh.freq_scale = br.read(2)? as u8;
+ sbrh.alter_scale = br.read_bool()?;
+ sbrh.noise_bands = br.read(2)? as u8;
+ }
+ if header_extra_2 {
+ sbrh.limiter_bands = br.read(2)? as u8;
+ sbrh.limiter_gains = br.read(2)? as u8;
+ sbrh.interpol_freq = br.read_bool()?;
+ if !sbrh.interpol_freq {
+ return Err(DecoderError::NotImplemented);
+ }
+ sbrh.smoothing_mode = br.read_bool()?;
+ }
+ Ok(sbrh)
+ }
+
+ pub fn differs_from(&self, rval: &Self) -> bool {
+ self.start_freq != rval.start_freq ||
+ self.stop_freq != rval.stop_freq ||
+ self.xover_band != rval.xover_band ||
+ self.freq_scale != rval.freq_scale ||
+ self.alter_scale != rval.alter_scale ||
+ self.noise_bands != rval.noise_bands
+ }
+}
+
+#[derive(Clone)]
+pub struct SBRState {
+ num_env_bands: [usize; 2],
+ num_master: usize,
+ num_noise_bands: usize,
+ num_lim: usize,
+ k_x: usize,
+ low_to_high_res: [usize; SBR_BANDS],
+ high_to_low_res: [usize; SBR_BANDS],
+ f: [usize; SBR_BANDS],
+ f_low: [usize; SBR_BANDS],
+ f_noise: [usize; SBR_BANDS],
+ f_lim: [usize; SBR_BANDS],
+ patch_num_subbands: [usize; SBR_BANDS],
+ patch_start_subband: [usize; SBR_BANDS],
+ num_patches: usize,
+}
+
+impl SBRState {
+ pub fn new() -> Self {
+ Self {
+ num_env_bands: [0; 2],
+ num_master: 0,
+ num_noise_bands: 0,
+ num_lim: 0,
+ k_x: 0,
+ low_to_high_res: [0; SBR_BANDS],
+ high_to_low_res: [0; SBR_BANDS],
+ f: [0; SBR_BANDS],
+ f_low: [0; SBR_BANDS],
+ f_noise: [0; SBR_BANDS],
+ f_lim: [0; SBR_BANDS],
+ patch_num_subbands: [0; SBR_BANDS],
+ patch_start_subband: [0; SBR_BANDS],
+ num_patches: 0,
+ }
+ }
+ pub fn init(&mut self, hdr: &SBRHeader, srate: u32) -> DecoderResult<()> {
+ let offset_tab = match srate {
+ 0..=16000 => &SBR_OFFSETS[0],
+ 16001..=22050 => &SBR_OFFSETS[1],
+ 22051..=24000 => &SBR_OFFSETS[2],
+ 24001..=32000 => &SBR_OFFSETS[3],
+ 32001..=64000 => &SBR_OFFSETS[4],
+ _ => &SBR_OFFSETS[5],
+ };
+ let smult = match srate {
+ 0..=31999 => 3000,
+ 32000..=63999 => 4000,
+ _ => 5000,
+ };
+ let start_min = (128 * smult + srate / 2) / srate;
+ let stop_min = (128 * smult * 2 + srate / 2) / srate;
+
+ let k0 = ((start_min as i32) + i32::from(offset_tab[hdr.start_freq])).max(0) as usize;
+ let k2 = (match hdr.stop_freq {
+ 14 => 2 * k0,
+ 15 => 3 * k0,
+ _ => {
+ let mut stop_dk = [0; 14];
+ generate_vdk(&mut stop_dk, stop_min as usize, SBR_BANDS, 13);
+ let dk_sum: usize = stop_dk[..hdr.stop_freq].iter().sum();
+ (stop_min as usize) + dk_sum
+ },
+ }).min(SBR_BANDS);
+
+ let max_bands = match srate {
+ 0..=32000 => 48,
+ 32001..=47999 => 35,
+ _ => 32,
+ };
+ validate!(k2 - k0 <= max_bands);
+
+ self.num_master = calculate_master_frequencies(&mut self.f, k0, k2, hdr);
+ let num_high = self.num_master - hdr.xover_band;
+ let num_low = (num_high + 1) / 2; // INT(num_high / 2) + (num_high - 2 * INT(num_high / 2))
+
+ self.num_env_bands = [num_low, num_high];
+
+ let f_high = &self.f[hdr.xover_band..];
+ let m = f_high[num_high] - f_high[0];
+ let k_x = f_high[0];
+ self.k_x = k_x;
+ self.f_low = [0; SBR_BANDS];
+ if (num_high & 1) == 0 {
+ for k in 0..=num_low {
+ self.f_low[k] = f_high[k * 2];
+ }
+ } else {
+ self.f_low[0] = f_high[0];
+ for k in 1..=num_low {
+ self.f_low[k] = f_high[k * 2 - 1];
+ }
+ }
+
+ let high_src = &f_high[..=num_high];
+ let low_src = &self.f_low[..=num_low];
+ for (dst, low) in self.high_to_low_res.iter_mut().zip(low_src.iter()) {
+ if let Ok(idx) = high_src.binary_search(low) {
+ *dst = idx;
+ } else {
+ return Err(DecoderError::Bug);
+ }
+ }
+ for (dst, high) in self.low_to_high_res.iter_mut().zip(high_src.iter()) {
+ match low_src.binary_search(high) {
+ Ok(idx) | Err(idx) => *dst = idx,
+ };
+ }
+
+ let num_q = (((hdr.noise_bands as f32) * ((k2 as f32) / (k_x as f32)).log2()).round() as usize).max(1);
+ self.num_noise_bands = num_q;
+ self.f_noise = [0; SBR_BANDS];
+ let mut prev = 0;
+ self.f_noise[0] = self.f_low[0];
+ for k in 1..=num_q {
+ let idx = prev + ((num_low - prev) / (num_q + 1 - k));
+ self.f_noise[k] = self.f_low[idx];
+ prev = idx;
+ }
+
+ let mut num_patches = 0;
+ self.patch_num_subbands = [0; SBR_BANDS];
+ self.patch_start_subband = [0; SBR_BANDS];
+ let mut msb = k0;
+ let mut usb = k_x;
+ let goal_sb = ((2048000 + srate / 2) / srate) as usize;
+ let last_band = k_x + m;
+ let mut k = if goal_sb < last_band {
+ let mut kk = 0;
+ for i in 0..self.num_master {
+ if self.f[i] >= goal_sb {
+ break;
+ }
+ kk = i + 1;
+ }
+ kk
+ } else {
+ self.num_master
+ };
+ loop {
+ let mut sb;
+ let mut odd;
+ let mut j = k;
+ loop {
+ sb = self.f[j];
+ odd = (sb - 2 + k0) & 1;
+ if sb <= k0 + msb - 1 - odd {
+ break;
+ }
+ j -= 1;
+ }
+
+ self.patch_num_subbands[num_patches] = sb.saturating_sub(usb);
+ self.patch_start_subband[num_patches] = k0 - odd - self.patch_num_subbands[num_patches];
+
+ if self.patch_num_subbands[num_patches] > 0 {
+ usb = sb;
+ msb = sb;
+ num_patches += 1;
+ } else {
+ msb = k_x;
+ }
+
+ if self.f[k] < sb + 3 {
+ k = self.num_master;
+ }
+
+ if sb == last_band {
+ break;
+ }
+ }
+ if (num_patches > 1) && (self.patch_num_subbands[num_patches - 1] < 3) {
+ num_patches -= 1;
+ }
+ validate!(num_patches <= NUM_PATCHES);
+ self.num_patches = num_patches;
+
+ self.f_lim = [0; SBR_BANDS];
+ let num_l = if hdr.limiter_bands == 0 {
+ self.f_lim[0] = self.f_low[0];
+ self.f_lim[1] = self.f_low[num_low];
+ 1
+ } else {
+ let lim_bands = match hdr.limiter_bands {
+ 1 => 1.2f32,
+ 2 => 2.0,
+ _ => 3.0,
+ };
+ let mut patch_borders = [0; NUM_PATCHES + 1];
+ patch_borders[0] = k_x;
+ for k in 0..num_patches {
+ patch_borders[k + 1] = patch_borders[k] + self.patch_num_subbands[k];
+ }
+ self.f_lim = self.f_low;
+ let f_lim_ptr = &mut self.f_lim[..num_low + num_patches];
+ for &pborder in patch_borders[1..num_patches].iter() {
+ let mut i = 0;
+ for &el in f_lim_ptr.iter() {
+ if el > pborder {
+ break;
+ }
+ i += 1;
+ }
+ for j in (i..num_low + num_patches - 1).rev() {
+ f_lim_ptr[j + 1] = f_lim_ptr[j];
+ }
+ f_lim_ptr[i] = pborder;
+ }
+ let mut nr_lim = num_low + num_patches - 1;
+ let mut k = 1;
+ let pbord = &patch_borders[..=num_patches];
+ while k <= nr_lim {
+ let n_octaves = ((self.f_lim[k] as f32) / (self.f_lim[k - 1] as f32)).log2();
+ if (n_octaves * lim_bands) < 0.49 {
+ if self.f_lim[k] == self.f_lim[k - 1] || !pbord.contains(&self.f_lim[k]) {
+ for l in k..nr_lim {
+ self.f_lim[l] = self.f_lim[l + 1];
+ }
+ nr_lim -= 1;
+ } else if !pbord.contains(&self.f_lim[k - 1]) {
+ for l in (k - 1)..nr_lim {
+ self.f_lim[l] = self.f_lim[l + 1];
+ }
+ nr_lim -= 1;
+ } else {
+ k += 1;
+ }
+ } else {
+ k += 1;
+ }
+ }
+
+ nr_lim
+ };
+ self.num_lim = num_l;
+
+ Ok(())
+ }
+}
+
+fn generate_vdk(v_dk: &mut [usize], k0: usize, k1: usize, num_bands: usize) {
+ let mut last = k0;
+ let k0 = k0 as f64;
+ let factor = (k1 as f64) / k0;
+ for k in 0..num_bands {
+ let next = (k0 * factor.powf((k + 1) as f64 / (num_bands as f64))).round() as usize;
+ let newval = next - last;
+ last = next;
+ let mut idx = k;
+ for (j, &el) in v_dk[..k].iter().enumerate() {
+ if newval < el {
+ idx = j;
+ break;
+ }
+ }
+ for j in (idx..k).rev() {
+ v_dk[j + 1] = v_dk[j];
+ }
+ v_dk[idx] = newval;
+ }
+}
+
+fn calculate_master_frequencies(f: &mut [usize; SBR_BANDS], k0: usize, k2: usize, hdr: &SBRHeader) -> usize {
+ if hdr.freq_scale == 0 {
+ let (dk, num_bands) = if !hdr.alter_scale {
+ (1, 2 * ((k2 - k0) / 2))
+ } else {
+ (2, 2 * ((k2 - k0 + 2) / (2 * 2)))
+ };
+ let k2_achieved = k0 + num_bands * dk;
+ let mut k2_diff = (k2 as isize) - (k2_achieved as isize);
+ let mut v_dk = [dk; SBR_BANDS];
+ if k2_diff < 0 {
+ let mut k = 0;
+ while k2_diff != 0 {
+ v_dk[k] -= 1;
+ k += 1;
+ k2_diff += 1;
+ }
+ } else if k2_diff > 0 {
+ let mut k = num_bands - 1;
+ while k2_diff != 0 {
+ v_dk[k] += 1;
+ k -= 1;
+ k2_diff -= 1;
+ }
+ }
+ f[0] = k0;
+ for i in 0..num_bands {
+ f[i + 1] = f[i] + v_dk[i];
+ }
+
+ num_bands
+ } else {
+ let bands = 14 - hdr.freq_scale * 2;
+ let warp = if !hdr.alter_scale { 1.0f32 } else { 1.3f32 };
+ let two_regions = (k2 as f32) / (k0 as f32) > 2.2449;
+ let k1 = if two_regions { 2 * k0 } else { k2 };
+ let num_bands0 = 2 * (((bands as f32) * ((k1 as f32) / (k0 as f32)).log2() / 2.0).round() as usize);
+ let mut v_dk0 = [0; SBR_BANDS];
+ generate_vdk(&mut v_dk0, k0, k1, num_bands0);
+ let mut v_k0 = [0; SBR_BANDS];
+ v_k0[0] = k0;
+ for i in 0..num_bands0 {
+ v_k0[i + 1] = v_k0[i] + v_dk0[i];
+ }
+
+ if two_regions {
+ let num_bands1 = 2 * (((bands as f32) * ((k2 as f32) / (k1 as f32)).log2() / (2.0 * warp)).round() as usize);
+ let mut v_dk1 = [0; SBR_BANDS];
+ generate_vdk(&mut v_dk1, k1, k2, num_bands1);
+ let max_vdk0 = v_dk0[num_bands0 - 1];
+ if v_dk1[0] < max_vdk0 {
+ let change = (max_vdk0 - v_dk1[0]).min((v_dk1[num_bands1 - 1] - v_dk1[0]) / 2);
+ v_dk1[0] += change;
+ v_dk1[num_bands1 - 1] -= change;
+ }
+ let mut v_k1 = [0; SBR_BANDS];
+ v_k1[0] = k1;
+ for i in 0..num_bands1 {
+ v_k1[i + 1] = v_k1[i] + v_dk1[i];
+ }
+ f[..=num_bands0].copy_from_slice(&v_k0[..=num_bands0]);
+ f[num_bands0 + 1..][..=num_bands1].copy_from_slice(&v_k1[1..][..=num_bands1]);
+ num_bands0 + num_bands1
+ } else {
+ f[..=num_bands0].copy_from_slice(&v_k0[..=num_bands0]);
+ num_bands0
+ }
+ }
+}
+
+const SBR_OFFSETS: [[i8; 16]; 6] = [
+ [ -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7 ], // 16kHz
+ [ -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13 ], // 22kHz
+ [ -5, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16 ], // 24kHz
+ [ -6, -4, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16 ], // 32kHz
+ [ -4, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16, 20 ], // 44kHz
+ [ -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16, 20, 24 ] // 64kHz
+];
--- /dev/null
+use super::*;
+use super::bs::FrameClass;
+use super::dsp::{SBRAnalysis, SBRSynthesis};
+use nihav_codec_support::dsp::fft::{FFTComplex, FFTC_ZERO};
+
+const RANGE: f32 = 65536.0;
+
+const SMOOTH_DELAY: usize = 4;
+
+const NEW_BW: [[f32; 4]; 4] = [
+ [ 0.0, 0.6, 0.9, 0.98 ],
+ [ 0.6, 0.75, 0.9, 0.98 ],
+ [ 0.0, 0.75, 0.9, 0.98 ],
+ [ 0.0, 0.75, 0.9, 0.98 ]
+];
+
+#[derive(Clone, Copy)]
+pub enum QuantMode {
+ Single,
+ Left,
+ Right,
+}
+
+#[derive(Clone)]
+pub struct SBRChannel {
+ sbr_a: SBRAnalysis,
+ sbr_s: SBRSynthesis,
+
+ w: [[FFTComplex; SBR_BANDS]; QMF_DELAY + MAX_SLOTS * 2],
+ x: [[FFTComplex; SBR_BANDS]; QMF_DELAY + MAX_SLOTS * 2],
+ x_high: [[FFTComplex; SBR_BANDS]; QMF_DELAY + MAX_SLOTS * 2],
+ y: [[FFTComplex; SBR_BANDS]; QMF_DELAY + MAX_SLOTS * 2],
+ prev_y: [[FFTComplex; SBR_BANDS]; QMF_DELAY + MAX_SLOTS * 2],
+
+ bw_array: [f32; SBR_BANDS],
+ old_bw_array: [f32; SBR_BANDS],
+
+ pub qmode: QuantMode,
+ pub fclass: FrameClass,
+ pub amp_res: bool,
+ pub num_env: usize,
+ prev_num_env: usize,
+ pub freq_res: [bool; NUM_ENVELOPES],
+ pub env_border: [usize; NUM_ENVELOPES],
+ pub noise_env_border: [usize; 3],
+ pub pointer: u8,
+ pub num_noise: usize,
+ pub last_env_end: usize,
+
+ pub df_env: [bool; NUM_ENVELOPES],
+ pub df_noise: [bool; 2],
+
+ pub invf_mode: [u8; NUM_PATCHES],
+ old_invf_mode: [u8; NUM_PATCHES],
+
+ pub data_env: [[i8; SBR_BANDS]; NUM_PATCHES],
+ pub data_noise: [[i8; SBR_BANDS]; NUM_PATCHES],
+ pub data_env2: [[i8; SBR_BANDS]; NUM_PATCHES],
+ pub data_noise2: [[i8; SBR_BANDS]; NUM_PATCHES],
+ pub last_envelope: [i8; SBR_BANDS],
+ pub last_noise_env: [i8; SBR_BANDS],
+ pub last_freq_res: bool,
+
+ pub add_harmonic: [bool; SBR_BANDS],
+ prev_l_a: i8,
+
+ s_idx_mapped: [[bool; SBR_BANDS]; NUM_ENVELOPES],
+ prev_s_idx_mapped: [bool; SBR_BANDS],
+ index_sine: usize,
+ index_noise: usize,
+ g_temp: [[f32; SBR_BANDS]; MAX_SLOTS * 2 + QMF_DELAY + SMOOTH_DELAY],
+ q_temp: [[f32; SBR_BANDS]; MAX_SLOTS * 2 + QMF_DELAY + SMOOTH_DELAY],
+}
+
+impl SBRChannel {
+ pub fn new() -> Self {
+ Self {
+ sbr_a: SBRAnalysis::new(),
+ sbr_s: SBRSynthesis::new(),
+
+ w: [[FFTC_ZERO; SBR_BANDS]; QMF_DELAY + MAX_SLOTS * 2],
+ x: [[FFTC_ZERO; SBR_BANDS]; QMF_DELAY + MAX_SLOTS * 2],
+ x_high: [[FFTC_ZERO; SBR_BANDS]; QMF_DELAY + MAX_SLOTS * 2],
+ y: [[FFTC_ZERO; SBR_BANDS]; QMF_DELAY + MAX_SLOTS * 2],
+ prev_y: [[FFTC_ZERO; SBR_BANDS]; QMF_DELAY + MAX_SLOTS * 2],
+
+ bw_array: [0.0; SBR_BANDS],
+ old_bw_array: [0.0; SBR_BANDS],
+
+ qmode: QuantMode::Single,
+ fclass: FrameClass::FixFix,
+ amp_res: false,
+ num_env: 0,
+ prev_num_env: 0,
+ freq_res: [false; NUM_ENVELOPES],
+ env_border: [0; NUM_ENVELOPES],
+ noise_env_border: [0; 3],
+ pointer: 0,
+ num_noise: 0,
+ last_env_end: 0,
+
+ df_env: [false; NUM_ENVELOPES],
+ df_noise: [false; 2],
+
+ invf_mode: [0; NUM_PATCHES],
+ old_invf_mode: [0; NUM_PATCHES],
+
+ data_env: [[0; SBR_BANDS]; NUM_PATCHES],
+ data_noise: [[0; SBR_BANDS]; NUM_PATCHES],
+ data_env2: [[0; SBR_BANDS]; NUM_PATCHES],
+ data_noise2: [[0; SBR_BANDS]; NUM_PATCHES],
+ last_envelope: [0; SBR_BANDS],
+ last_noise_env: [0; SBR_BANDS],
+ last_freq_res: false,
+
+ add_harmonic: [false; SBR_BANDS],
+ prev_l_a: -1,
+
+ s_idx_mapped: [[false; SBR_BANDS]; NUM_ENVELOPES],
+ prev_s_idx_mapped: [false; SBR_BANDS],
+ index_sine: 0,
+ index_noise: 0,
+ g_temp: [[0.0; SBR_BANDS]; MAX_SLOTS * 2 + QMF_DELAY + SMOOTH_DELAY],
+ q_temp: [[0.0; SBR_BANDS]; MAX_SLOTS * 2 + QMF_DELAY + SMOOTH_DELAY],
+ }
+ }
+
+ pub fn reset(&mut self) {
+ self.prev_y = [[FFTC_ZERO; SBR_BANDS]; QMF_DELAY + MAX_SLOTS * 2];
+ self.old_bw_array = [0.0; SBR_BANDS];
+ self.last_envelope = [0; SBR_BANDS];
+ self.last_noise_env = [0; SBR_BANDS];
+ self.last_freq_res = false;
+ self.last_env_end = 0;
+ self.prev_num_env = 0;
+ self.old_invf_mode = [0; NUM_PATCHES];
+ self.prev_s_idx_mapped = [false; SBR_BANDS];
+ self.index_sine = 0;
+ self.index_noise = 0;
+ }
+
+ pub fn set_amp_res(&mut self, amp_res: bool) {
+ if self.fclass != FrameClass::FixFix || self.num_env != 1 {
+ self.amp_res = amp_res;
+ } else {
+ self.amp_res = false;
+ }
+ }
+
+ pub fn analysis(&mut self, dsp: &mut SBRDSP, src: &[f32]) {
+ for (src, dst) in src.chunks(32).zip(self.w[QMF_DELAY..].iter_mut()) {
+ self.sbr_a.analysis(dsp, src, dst);
+ }
+ }
+ pub fn synthesis(&mut self, dsp: &mut SBRDSP, dst: &mut [f32]) {
+ for (src, dst) in self.x.iter().zip(dst.chunks_mut(64)) {
+ self.sbr_s.synthesis(dsp, src, dst);
+ }
+ }
+ pub fn bypass(&mut self) {
+ self.x.copy_from_slice(&self.w);
+ }
+ pub fn hf_generate(&mut self, state: &SBRState) {
+ for (x, w) in self.x.iter_mut().zip(self.w.iter()) {
+ x[..state.k_x].copy_from_slice(&w[..state.k_x]);
+ for el in x[state.k_x..].iter_mut() {
+ *el = FFTC_ZERO;
+ }
+ }
+
+ let mut phi = [[[FFTC_ZERO; SBR_BANDS]; 3]; 3];
+ let mut a0 = [FFTC_ZERO; SBR_BANDS];
+ let mut a1 = [FFTC_ZERO; SBR_BANDS];
+ let k0 = state.f[0];
+ for (i, phi) in phi.iter_mut().enumerate() {
+ for (j, phi) in phi.iter_mut().enumerate().skip(1) {
+ let src0 = &self.x[HF_ADJ - i..][..MAX_SLOTS * 2 + 6 - 1];
+ let src1 = &self.x[HF_ADJ - j..][..MAX_SLOTS * 2 + 6 - 1];
+ for (slot0, slot1) in src0.iter().zip(src1.iter()) {
+ for (k, phi) in phi.iter_mut().take(k0).enumerate() {
+ *phi += slot0[k] * !slot1[k];
+ }
+ }
+ }
+ }
+ for (k, (a0, a1)) in a0.iter_mut().zip(a1.iter_mut()).take(k0).enumerate() {
+ let phi12 = phi[1][2][k];
+ let d_k = phi[2][2][k].re * phi[1][1][k].re - phi12.sq_modulus() / (1.0 + 1.0e-6);
+
+ if d_k != 0.0 {
+ *a1 = (phi[0][1][k] * phi[1][2][k] - phi[0][2][k] * phi[1][1][k]).scale(1.0 / d_k);
+ }
+ if phi[1][1][k].re != 0.0 {
+ *a0 = -(phi[0][1][k] + *a1 * !phi[1][2][k]).scale(1.0 / phi[1][1][k].re);
+ }
+ if a0.sq_modulus() >= 4.0*4.0 || a1.sq_modulus() >= 4.0*4.0 {
+ *a0 = FFTC_ZERO;
+ *a1 = FFTC_ZERO;
+ }
+ }
+
+ for k in 0..state.num_noise_bands {
+ let new_bw = NEW_BW[self.old_invf_mode[k] as usize][self.invf_mode[k] as usize];
+ let old_bw = self.old_bw_array[k];
+ let temp_bw = if new_bw < old_bw {
+ 0.75 * new_bw + 0.25 * old_bw
+ } else {
+ 0.90625 * new_bw + 0.09375 * old_bw
+ };
+ self.bw_array[k] = if temp_bw >= 0.015625 {
+ temp_bw
+ } else {
+ 0.0
+ };
+ }
+
+ for (l, x_high) in self.x_high.iter_mut().enumerate().skip(HF_ADJ).take(self.env_border[self.num_env - 1] * 2) {
+ *x_high = [FFTC_ZERO; SBR_BANDS];
+ let mut dst_k = state.k_x;
+ for (&patch_start, &patch_len) in state.patch_start_subband[..state.num_patches].iter().zip(state.patch_num_subbands.iter()) {
+ for (k, dst) in x_high[dst_k..][..patch_len].iter_mut().enumerate() {
+ let p = patch_start + k;
+ let cur_x = self.x[l][p];
+ let prev_x = self.x[l - 1][p];
+ let pprev_x = self.x[l - 2][p];
+ let g_k = match state.f_noise[..state.num_noise_bands].binary_search(&k) {
+ Ok(idx) | Err(idx) => idx.min(state.num_noise_bands - 1),
+ };
+ let bw_val = self.bw_array[g_k];
+ *dst = cur_x + a0[p] * prev_x.scale(bw_val) + a1[p] * pprev_x.scale(bw_val * bw_val);
+ }
+ dst_k += patch_len;
+ }
+ }
+ }
+ pub fn hf_adjust(&mut self, state: &SBRState, hdr: &SBRHeader) {
+ const LIM_GAIN: [f32; 4] = [0.70795, 1.0, 1.41254, 10000.0];
+ const H_SMOOTH: [f32; 5] = [
+ 1.0 / 3.0, 0.30150283239582, 0.21816949906249, 0.11516383427084, 0.03183050093751
+ ];
+ const PHI: [FFTComplex; 4] = [
+ FFTComplex{ re: 1.0, im: 0.0 },
+ FFTComplex{ re: 0.0, im: 1.0 },
+ FFTComplex{ re: -1.0, im: 0.0 },
+ FFTComplex{ re: 0.0, im: -1.0 },
+ ];
+
+ let kx = state.k_x;
+ let km = state.f[state.num_master];
+ let envelope_end = self.env_border[self.num_env - 1];
+
+ let high_start = state.f[..=state.num_master].binary_search(&state.k_x).unwrap();
+ let f_high = &state.f[..=state.num_master][high_start..];
+ let f_low = &state.f_low[..=state.num_env_bands[0]];
+
+ let l_a = match (self.fclass, self.pointer) {
+ (_, 0) => -1,
+ (FrameClass::FixFix, _) => -1,
+ (FrameClass::FixVar, _) |
+ (FrameClass::VarVar, _) => (self.num_env as i8) + 1 - (self.pointer as i8),
+ (FrameClass::VarFix, 1) => -1,
+ (FrameClass::VarFix, _) => (self.pointer as i8) - 1,
+ };
+
+ self.s_idx_mapped = [[false; SBR_BANDS]; NUM_ENVELOPES];
+ for (l, s_idx_mapped) in self.s_idx_mapped[..self.num_env].iter_mut().enumerate() {
+ let mut start = f_high[0];
+ for (i, &end) in f_high.iter().skip(1).enumerate() {
+ if self.add_harmonic[i] {
+ let mid = (start + end) / 2;
+ if ((l as i8) >= l_a) || self.prev_s_idx_mapped[mid] {
+ s_idx_mapped[mid] = true;
+ }
+ }
+ start = end;
+ }
+ }
+ self.prev_s_idx_mapped = self.s_idx_mapped[self.num_env - 1];
+
+ let mut s_mapped = [[false; SBR_BANDS]; NUM_ENVELOPES];
+ for ((s_mapped, s_idx_mapped), &freq_res) in s_mapped.iter_mut().zip(self.s_idx_mapped[..self.num_env].iter()).zip(self.freq_res.iter()) {
+ let mut band_start = kx;
+ if freq_res {
+ for (&add_sine, &band_end) in self.add_harmonic.iter().zip(f_high[1..].iter()) {
+ for el in s_mapped[band_start..band_end].iter_mut() {
+ *el = add_sine;
+ }
+ band_start = band_end;
+ }
+ } else {
+ for &band_end in f_low[1..].iter() {
+ let add_sine = s_idx_mapped[band_start..band_end].contains(&true);
+ for el in s_mapped[band_start..band_end].iter_mut() {
+ *el = add_sine;
+ }
+ band_start = band_end;
+ }
+ }
+ }
+
+ let mut e_orig_mapped = [[0.0; SBR_BANDS]; NUM_ENVELOPES];
+ let (a, pan_offset) = if self.amp_res { (1.0, 12.0) } else { (0.5, 24.0) };
+ match self.qmode {
+ QuantMode::Single => {
+ for (dst, (src, &freq_res)) in e_orig_mapped[..self.num_env].iter_mut().zip(self.data_env.iter().zip(self.freq_res.iter())) {
+ let bands = if freq_res { f_high } else { f_low };
+ let mut start = kx;
+ for (&val, &band_end) in src.iter().zip(bands.iter().skip(1)) {
+ let scale = 2.0f32.powf(6.0 + f32::from(val) * a);
+ for dst in dst[start..band_end].iter_mut() {
+ *dst = scale;
+ }
+ start = band_end;
+ }
+ }
+ },
+ QuantMode::Left => {
+ for (dst, ((e0, e1), &freq_res)) in e_orig_mapped[..self.num_env].iter_mut().zip(self.data_env.iter().zip(self.data_env2.iter()).zip(self.freq_res.iter())) {
+ let bands = if freq_res { f_high } else { f_low };
+ let mut start = kx;
+ for ((&e0, &e1), &band_end) in e0.iter().zip(e1.iter()).zip(bands.iter().skip(1)) {
+ let scale = 2.0f32.powf(6.0 + f32::from(e0) * a + 1.0) / (1.0 + 2.0f32.powf((pan_offset - f32::from(e1)) * a));
+ for dst in dst[start..band_end].iter_mut() {
+ *dst = scale;
+ }
+ start = band_end;
+ }
+ }
+ },
+ QuantMode::Right => {
+ for (dst, ((e0, e1), &freq_res)) in e_orig_mapped[..self.num_env].iter_mut().zip(self.data_env2.iter().zip(self.data_env.iter()).zip(self.freq_res.iter())) {
+ let bands = if freq_res { f_high } else { f_low };
+ let mut start = kx;
+ for ((&e0, &e1), &band_end) in e0.iter().zip(e1.iter()).zip(bands.iter().skip(1)) {
+ let scale = 2.0f32.powf(6.0 + f32::from(e0) * a + 1.0) / (1.0 + 2.0f32.powf((f32::from(e1) - pan_offset) * a));
+ for dst in dst[start..band_end].iter_mut() {
+ *dst = scale;
+ }
+ start = band_end;
+ }
+ }
+ }
+ };
+ let mut q_mapped = [[0.0; SBR_BANDS]; NUM_ENVELOPES];
+ let mut start = 0;
+ let noise_env = [0, self.noise_env_border[0], self.noise_env_border[1]];
+ match self.qmode {
+ QuantMode::Single => {
+ for (env_no, &env_end) in self.env_border[..self.num_env].iter().enumerate() {
+ let env_end = env_end;
+ let mut noise_env_no = 0;
+ for nenv in 0..self.num_noise {
+ if (start >= noise_env[nenv]) && (env_end <= noise_env[nenv + 1]) {
+ noise_env_no = nenv;
+ break;
+ }
+ }
+ let mut band_start = state.f_noise[0];
+ for (noise_band, &band_end) in state.f_noise[1..=state.num_noise_bands].iter().enumerate() {
+ let scale = 2.0f32.powf(6.0 - f32::from(self.data_noise[noise_env_no][noise_band]));
+ for el in q_mapped[env_no][band_start..band_end].iter_mut() {
+ *el = scale;
+ }
+ band_start = band_end;
+ }
+ start = env_end;
+ }
+ },
+ QuantMode::Left => {
+ for (env_no, &env_end) in self.env_border[..self.num_env].iter().enumerate() {
+ let env_end = env_end;
+ let mut noise_env_no = 0;
+ for nenv in 0..self.num_noise {
+ if (start >= noise_env[nenv]) && (env_end <= noise_env[nenv + 1]) {
+ noise_env_no = nenv;
+ break;
+ }
+ }
+ let mut band_start = state.f_noise[0];
+ for (noise_band, &band_end) in state.f_noise[1..=state.num_noise_bands].iter().enumerate() {
+ let scale = 2.0f32.powf(6.0 - f32::from(self.data_noise[noise_env_no][noise_band]) + 1.0) / (1.0 + 2.0f32.powf(12.0 - f32::from(self.data_noise2[noise_env_no][noise_band])));
+ for el in q_mapped[env_no][band_start..band_end].iter_mut() {
+ *el = scale;
+ }
+ band_start = band_end;
+ }
+ start = env_end;
+ }
+ },
+ QuantMode::Right => {
+ for (env_no, &env_end) in self.env_border[..self.num_env].iter().enumerate() {
+ let env_end = env_end;
+ let mut noise_env_no = 0;
+ for nenv in 0..self.num_noise {
+ if (start >= noise_env[nenv]) && (env_end <= noise_env[nenv + 1]) {
+ noise_env_no = nenv;
+ break;
+ }
+ }
+ let mut band_start = state.f_noise[0];
+ for (noise_band, &band_end) in state.f_noise[1..=state.num_noise_bands].iter().enumerate() {
+ let scale = 2.0f32.powf(6.0 - f32::from(self.data_noise2[noise_env_no][noise_band]) + 1.0) / (1.0 + 2.0f32.powf(f32::from(self.data_noise[noise_env_no][noise_band]) - 12.0));
+ for el in q_mapped[env_no][band_start..band_end].iter_mut() {
+ *el = scale;
+ }
+ band_start = band_end;
+ }
+ start = env_end;
+ }
+ },
+ };
+
+ let mut start = 0;
+ let mut e_curr = [[0.0f32; SBR_BANDS]; NUM_ENVELOPES];
+ for (e_curr, &env_end) in e_curr.iter_mut().zip(self.env_border[..self.num_env].iter()) {
+ for slot in self.x_high[HF_ADJ..][(start * 2)..(env_end * 2)].iter() {
+ for (dst, x) in e_curr[kx..km].iter_mut().zip(slot[kx..km].iter()) {
+ *dst += x.sq_modulus();
+ }
+ }
+ for el in e_curr[kx..km].iter_mut() {
+ *el *= RANGE * RANGE;
+ *el /= ((env_end - start) * 2) as f32;
+ }
+ start = env_end;
+ }
+
+ const EPS: f32 = 1.0;
+ const EPS0: f32 = 1.0e-12;
+ let la_prev = if self.prev_l_a == (self.prev_num_env as i8) { 0 } else { -1 };
+ let mut g_max_tmp;
+ let mut g_boost_tmp;
+ let mut g = [0.0; SBR_BANDS];
+ let mut q_m = [0.0; SBR_BANDS];
+ let mut s_m = [0.0; SBR_BANDS];
+ let mut q_m_lim = [0.0; SBR_BANDS];
+ let mut g_lim = [0.0; SBR_BANDS];
+ let mut g_lim_boost = [[0.0; SBR_BANDS]; NUM_ENVELOPES];
+ let mut q_m_lim_boost = [[0.0; SBR_BANDS]; NUM_ENVELOPES];
+ let mut s_m_boost = [[0.0; SBR_BANDS]; NUM_ENVELOPES];
+ for env in 0..self.num_env {
+ let mut start = kx;
+ g_max_tmp = [0.0; SBR_BANDS];
+ g_boost_tmp = [0.0; SBR_BANDS];
+ for (dst, &end) in g_max_tmp.iter_mut().zip(state.f_lim[1..=state.num_lim].iter()) {
+ let mut e_o_sum = EPS0;
+ let mut e_c_sum = EPS0;
+ for k in start..end {
+ e_o_sum += e_orig_mapped[env][k] as f32;
+ e_c_sum += e_curr[env][k];
+ }
+ *dst = (e_o_sum / e_c_sum).sqrt() * LIM_GAIN[hdr.limiter_gains as usize];
+ start = end;
+ }
+ for k in kx..km {
+ let e_orig = e_orig_mapped[env][k] as f32;
+ let q_orig = q_mapped[env][k] as f32;
+ let e_curr = e_curr[env][k];
+
+ q_m[k] = (e_orig * q_orig / (1.0 + q_orig)).sqrt();
+ s_m[k] = if self.s_idx_mapped[env][k] { (e_orig / (1.0 + q_orig)).sqrt() } else { 0.0 };
+ g[k] = if !s_mapped[env][k] {
+ let q_add = if (env as i8) != l_a && (env as i8) != la_prev { q_orig } else { 0.0 };
+ (e_orig / ((EPS + e_curr) * (1.0 + q_add))).sqrt()
+ } else {
+ (e_orig / (EPS + e_curr) * q_orig / (1.0 + q_orig)).sqrt()
+ };
+
+ let mut lidx = 0;
+ for i in 0..state.num_lim {
+ if (state.f_lim[i] <= k) && (k < state.f_lim[i + 1]) {
+ lidx = i;
+ break;
+ }
+ }
+
+ let g_max = g_max_tmp[lidx].min(1.0e5);
+ q_m_lim[k] = q_m[k].min(q_m[k] * g_max / g[k]);
+ g_lim[k] = g[k].min(g_max);
+ }
+ let mut start = kx;
+ for (lim_no, dst) in g_boost_tmp[..state.num_lim].iter_mut().enumerate() {
+ let end = state.f_lim[lim_no + 1];
+ let mut nsum = EPS0;
+ let mut dsum = EPS0;
+ for k in start..end {
+ nsum += e_orig_mapped[env][k] as f32;
+ dsum += e_curr[env][k] * g_lim[k] * g_lim[k];
+ if s_m[k] != 0.0 || (env as i8) == l_a || (env as i8) == la_prev {
+ dsum += s_m[k] * s_m[k];
+ } else {
+ dsum += q_m_lim[k] * q_m_lim[k];
+ }
+ }
+ *dst = (nsum / dsum).sqrt();
+ let g_boost = dst.min(1.584893192);
+ for k in start..end {
+ g_lim_boost[env][k] = g_lim[k] * g_boost;
+ q_m_lim_boost[env][k] = q_m_lim[k] * g_boost;
+ s_m_boost[env][k] = s_m[k] * g_boost;
+ }
+ start = end;
+ }
+ }
+
+ let mut env_map = [0; MAX_SLOTS * 2 + QMF_DELAY];
+ let mut start = 0;
+ for (env, &env_end) in self.env_border[..self.num_env].iter().enumerate() {
+ for l in (start * 2)..(env_end * 2) {
+ env_map[l] = env;
+ }
+ start = env_end;
+ }
+
+ let (ghead, gcur) = self.g_temp.split_at_mut(SMOOTH_DELAY);
+ let (qhead, qcur) = self.q_temp.split_at_mut(SMOOTH_DELAY);
+ if self.last_env_end > 0 {
+ ghead.copy_from_slice(&gcur[self.last_env_end - SMOOTH_DELAY..][..SMOOTH_DELAY]);
+ qhead.copy_from_slice(&qcur[self.last_env_end - SMOOTH_DELAY..][..SMOOTH_DELAY]);
+ let mut start = 0;
+ for (&env_end, (g_lim, q_lim)) in self.env_border[..self.num_env].iter().zip(g_lim_boost.iter().zip(q_m_lim_boost.iter())) {
+ for slot in (start * 2)..(env_end * 2) {
+ gcur[slot] = *g_lim;
+ qcur[slot] = *q_lim;
+ }
+ start = env_end;
+ }
+ } else {
+ for dst in ghead.iter_mut() {
+ *dst = g_lim_boost[0];
+ }
+ for dst in qhead.iter_mut() {
+ *dst = q_m_lim_boost[0];
+ }
+ let mut start = 0;
+ for (&env_end, (g_lim, q_lim)) in self.env_border[..self.num_env].iter().zip(g_lim_boost.iter().zip(q_m_lim_boost.iter())) {
+ for slot in (start * 2)..(env_end * 2) {
+ gcur[slot] = *g_lim;
+ qcur[slot] = *q_lim;
+ }
+ start = env_end;
+ }
+ }
+
+ let mut g_filt = [[0.0; SBR_BANDS]; MAX_SLOTS * 2 + QMF_DELAY];
+ let mut q_filt = [[0.0; SBR_BANDS]; MAX_SLOTS * 2 + QMF_DELAY];
+ if !hdr.smoothing_mode {
+ for slot in 0..(envelope_end * 2) {
+ if (slot as i8) == (la_prev * 2) {
+ g_filt[slot].copy_from_slice(&self.g_temp[slot + SMOOTH_DELAY]);
+ q_filt[slot].copy_from_slice(&self.q_temp[slot + SMOOTH_DELAY]);
+ continue;
+ }
+ for k in kx..km {
+ let mut gsum = 0.0;
+ let mut qsum = 0.0;
+ for (i, &coef) in H_SMOOTH.iter().enumerate() {
+ gsum += self.g_temp[slot + SMOOTH_DELAY - i][k] * coef;
+ qsum += self.q_temp[slot + SMOOTH_DELAY - i][k] * coef;
+ }
+ g_filt[slot][k] = gsum;
+ q_filt[slot][k] = qsum;
+ }
+ }
+ } else {
+ g_filt.copy_from_slice(gcur);
+ q_filt.copy_from_slice(qcur);
+ }
+
+ let index_noise = self.index_noise.wrapping_sub(self.env_border[0] * 2) & 511;
+ for (slot, y) in self.y.iter_mut().skip(HF_ADJ).take(envelope_end * 2).enumerate() {
+ for (k, y) in y.iter_mut().enumerate().skip(kx).take(km - kx) {
+ *y = self.x_high[HF_ADJ + slot][k].scale(g_filt[slot][k]);
+
+ let smb = s_m_boost[env_map[slot]][k] / RANGE;
+ if smb != 0.0 {
+ let mut s = FFTComplex { re: smb, im: smb };
+ if (k & 1) != 0 {
+ s = !s;
+ }
+ y.re += s.re * PHI[self.index_sine].re;
+ y.im += s.im * PHI[self.index_sine].im;
+ } else {
+ *y += SBR_NOISE_TABLE[(index_noise + slot * SBR_BANDS + k - kx + 1) & 511].scale(q_filt[slot][k] / RANGE);
+ }
+ }
+ self.index_sine = (self.index_sine + 1) & 3;
+ }
+ self.index_noise = (index_noise + km - kx) & 511;
+
+ let end = if self.last_env_end != 0 {
+ (self.last_env_end - MAX_SLOTS) * 2
+ } else {
+ 0
+ };
+ self.last_env_end = envelope_end;
+ for (i, x) in self.x[..end].iter_mut().enumerate() {
+ x[state.k_x..].copy_from_slice(&self.prev_y[HF_ADJ + MAX_SLOTS * 2 + i][state.k_x..]);
+ }
+ for (x, y) in self.x[end..].iter_mut().zip(self.y[HF_ADJ + end..].iter()) {
+ x[state.k_x..].copy_from_slice(&y[state.k_x..]);
+ }
+
+ self.prev_l_a = l_a;
+ }
+ pub fn update_frame(&mut self) {
+ let (start, tail) = self.w.split_at_mut(QMF_DELAY);
+ start.copy_from_slice(&tail[tail.len() - QMF_DELAY..]);
+ self.prev_y = self.y;
+ self.old_invf_mode = self.invf_mode;
+ self.old_bw_array = self.bw_array;
+
+ self.prev_num_env = self.num_env;
+ }
+}
+
+const SBR_NOISE_TABLE: [FFTComplex; 512] = [
+ FFTComplex{ re: -0.99948153278296, im: -0.59483417516607 },
+ FFTComplex{ re: 0.97113454393991, im: -0.67528515225647 },
+ FFTComplex{ re: 0.14130051758487, im: -0.95090983575689 },
+ FFTComplex{ re: -0.47005496701697, im: -0.37340549728647 },
+ FFTComplex{ re: 0.80705063769351, im: 0.29653668284408 },
+ FFTComplex{ re: -0.38981478896926, im: 0.89572605717087 },
+ FFTComplex{ re: -0.01053049862020, im: -0.66959058036166 },
+ FFTComplex{ re: -0.91266367957293, im: -0.11522938140034 },
+ FFTComplex{ re: 0.54840422910309, im: 0.75221367176302 },
+ FFTComplex{ re: 0.40009252867955, im: -0.98929400334421 },
+ FFTComplex{ re: -0.99867974711855, im: -0.88147068645358 },
+ FFTComplex{ re: -0.95531076805040, im: 0.90908757154593 },
+ FFTComplex{ re: -0.45725933317144, im: -0.56716323646760 },
+ FFTComplex{ re: -0.72929675029275, im: -0.98008272727324 },
+ FFTComplex{ re: 0.75622801399036, im: 0.20950329995549 },
+ FFTComplex{ re: 0.07069442601050, im: -0.78247898470706 },
+ FFTComplex{ re: 0.74496252926055, im: -0.91169004445807 },
+ FFTComplex{ re: -0.96440182703856, im: -0.94739918296622 },
+ FFTComplex{ re: 0.30424629369539, im: -0.49438267012479 },
+ FFTComplex{ re: 0.66565033746925, im: 0.64652935542491 },
+ FFTComplex{ re: 0.91697008020594, im: 0.17514097332009 },
+ FFTComplex{ re: -0.70774918760427, im: 0.52548653416543 },
+ FFTComplex{ re: -0.70051415345560, im: -0.45340028808763 },
+ FFTComplex{ re: -0.99496513054797, im: -0.90071908066973 },
+ FFTComplex{ re: 0.98164490790123, im: -0.77463155528697 },
+ FFTComplex{ re: -0.54671580548181, im: -0.02570928536004 },
+ FFTComplex{ re: -0.01689629065389, im: 0.00287506445732 },
+ FFTComplex{ re: -0.86110349531986, im: 0.42548583726477 },
+ FFTComplex{ re: -0.98892980586032, im: -0.87881132267556 },
+ FFTComplex{ re: 0.51756627678691, im: 0.66926784710139 },
+ FFTComplex{ re: -0.99635026409640, im: -0.58107730574765 },
+ FFTComplex{ re: -0.99969370862163, im: 0.98369989360250 },
+ FFTComplex{ re: 0.55266258627194, im: 0.59449057465591 },
+ FFTComplex{ re: 0.34581177741673, im: 0.94879421061866 },
+ FFTComplex{ re: 0.62664209577999, im: -0.74402970906471 },
+ FFTComplex{ re: -0.77149701404973, im: -0.33883658042801 },
+ FFTComplex{ re: -0.91592244254432, im: 0.03687901376713 },
+ FFTComplex{ re: -0.76285492357887, im: -0.91371867919124 },
+ FFTComplex{ re: 0.79788337195331, im: -0.93180971199849 },
+ FFTComplex{ re: 0.54473080610200, im: -0.11919206037186 },
+ FFTComplex{ re: -0.85639281671058, im: 0.42429854760451 },
+ FFTComplex{ re: -0.92882402971423, im: 0.27871809078609 },
+ FFTComplex{ re: -0.11708371046774, im: -0.99800843444966 },
+ FFTComplex{ re: 0.21356749817493, im: -0.90716295627033 },
+ FFTComplex{ re: -0.76191692573909, im: 0.99768118356265 },
+ FFTComplex{ re: 0.98111043100884, im: -0.95854459734407 },
+ FFTComplex{ re: -0.85913269895572, im: 0.95766566168880 },
+ FFTComplex{ re: -0.93307242253692, im: 0.49431757696466 },
+ FFTComplex{ re: 0.30485754879632, im: -0.70540034357529 },
+ FFTComplex{ re: 0.85289650925190, im: 0.46766131791044 },
+ FFTComplex{ re: 0.91328082618125, im: -0.99839597361769 },
+ FFTComplex{ re: -0.05890199924154, im: 0.70741827819497 },
+ FFTComplex{ re: 0.28398686150148, im: 0.34633555702188 },
+ FFTComplex{ re: 0.95258164539612, im: -0.54893416026939 },
+ FFTComplex{ re: -0.78566324168507, im: -0.75568541079691 },
+ FFTComplex{ re: -0.95789495447877, im: -0.20423194696966 },
+ FFTComplex{ re: 0.82411158711197, im: 0.96654618432562 },
+ FFTComplex{ re: -0.65185446735885, im: -0.88734990773289 },
+ FFTComplex{ re: -0.93643603134666, im: 0.99870790442385 },
+ FFTComplex{ re: 0.91427159529618, im: -0.98290505544444 },
+ FFTComplex{ re: -0.70395684036886, im: 0.58796798221039 },
+ FFTComplex{ re: 0.00563771969365, im: 0.61768196727244 },
+ FFTComplex{ re: 0.89065051931895, im: 0.52783352697585 },
+ FFTComplex{ re: -0.68683707712762, im: 0.80806944710339 },
+ FFTComplex{ re: 0.72165342518718, im: -0.69259857349564 },
+ FFTComplex{ re: -0.62928247730667, im: 0.13627037407335 },
+ FFTComplex{ re: 0.29938434065514, im: -0.46051329682246 },
+ FFTComplex{ re: -0.91781958879280, im: -0.74012716684186 },
+ FFTComplex{ re: 0.99298717043688, im: 0.40816610075661 },
+ FFTComplex{ re: 0.82368298622748, im: -0.74036047190173 },
+ FFTComplex{ re: -0.98512833386833, im: -0.99972330709594 },
+ FFTComplex{ re: -0.95915368242257, im: -0.99237800466040 },
+ FFTComplex{ re: -0.21411126572790, im: -0.93424819052545 },
+ FFTComplex{ re: -0.68821476106884, im: -0.26892306315457 },
+ FFTComplex{ re: 0.91851997982317, im: 0.09358228901785 },
+ FFTComplex{ re: -0.96062769559127, im: 0.36099095133739 },
+ FFTComplex{ re: 0.51646184922287, im: -0.71373332873917 },
+ FFTComplex{ re: 0.61130721139669, im: 0.46950141175917 },
+ FFTComplex{ re: 0.47336129371299, im: -0.27333178296162 },
+ FFTComplex{ re: 0.90998308703519, im: 0.96715662938132 },
+ FFTComplex{ re: 0.44844799194357, im: 0.99211574628306 },
+ FFTComplex{ re: 0.66614891079092, im: 0.96590176169121 },
+ FFTComplex{ re: 0.74922239129237, im: -0.89879858826087 },
+ FFTComplex{ re: -0.99571588506485, im: 0.52785521494349 },
+ FFTComplex{ re: 0.97401082477563, im: -0.16855870075190 },
+ FFTComplex{ re: 0.72683747733879, im: -0.48060774432251 },
+ FFTComplex{ re: 0.95432193457128, im: 0.68849603408441 },
+ FFTComplex{ re: -0.72962208425191, im: -0.76608443420917 },
+ FFTComplex{ re: -0.85359479233537, im: 0.88738125901579 },
+ FFTComplex{ re: -0.81412430338535, im: -0.97480768049637 },
+ FFTComplex{ re: -0.87930772356786, im: 0.74748307690436 },
+ FFTComplex{ re: -0.71573331064977, im: -0.98570608178923 },
+ FFTComplex{ re: 0.83524300028228, im: 0.83702537075163 },
+ FFTComplex{ re: -0.48086065601423, im: -0.98848504923531 },
+ FFTComplex{ re: 0.97139128574778, im: 0.80093621198236 },
+ FFTComplex{ re: 0.51992825347895, im: 0.80247631400510 },
+ FFTComplex{ re: -0.00848591195325, im: -0.76670128000486 },
+ FFTComplex{ re: -0.70294374303036, im: 0.55359910445577 },
+ FFTComplex{ re: -0.95894428168140, im: -0.43265504344783 },
+ FFTComplex{ re: 0.97079252950321, im: 0.09325857238682 },
+ FFTComplex{ re: -0.92404293670797, im: 0.85507704027855 },
+ FFTComplex{ re: -0.69506469500450, im: 0.98633412625459 },
+ FFTComplex{ re: 0.26559203620024, im: 0.73314307966524 },
+ FFTComplex{ re: 0.28038443336943, im: 0.14537913654427 },
+ FFTComplex{ re: -0.74138124825523, im: 0.99310339807762 },
+ FFTComplex{ re: -0.01752795995444, im: -0.82616635284178 },
+ FFTComplex{ re: -0.55126773094930, im: -0.98898543862153 },
+ FFTComplex{ re: 0.97960898850996, im: -0.94021446752851 },
+ FFTComplex{ re: -0.99196309146936, im: 0.67019017358456 },
+ FFTComplex{ re: -0.67684928085260, im: 0.12631491649378 },
+ FFTComplex{ re: 0.09140039465500, im: -0.20537731453108 },
+ FFTComplex{ re: -0.71658965751996, im: -0.97788200391224 },
+ FFTComplex{ re: 0.81014640078925, im: 0.53722648362443 },
+ FFTComplex{ re: 0.40616991671205, im: -0.26469008598449 },
+ FFTComplex{ re: -0.67680188682972, im: 0.94502052337695 },
+ FFTComplex{ re: 0.86849774348749, im: -0.18333598647899 },
+ FFTComplex{ re: -0.99500381284851, im: -0.02634122068550 },
+ FFTComplex{ re: 0.84329189340667, im: 0.10406957462213 },
+ FFTComplex{ re: -0.09215968531446, im: 0.69540012101253 },
+ FFTComplex{ re: 0.99956173327206, im: -0.12358542001404 },
+ FFTComplex{ re: -0.79732779473535, im: -0.91582524736159 },
+ FFTComplex{ re: 0.96349973642406, im: 0.96640458041000 },
+ FFTComplex{ re: -0.79942778496547, im: 0.64323902822857 },
+ FFTComplex{ re: -0.11566039853896, im: 0.28587846253726 },
+ FFTComplex{ re: -0.39922954514662, im: 0.94129601616966 },
+ FFTComplex{ re: 0.99089197565987, im: -0.92062625581587 },
+ FFTComplex{ re: 0.28631285179909, im: -0.91035047143603 },
+ FFTComplex{ re: -0.83302725605608, im: -0.67330410892084 },
+ FFTComplex{ re: 0.95404443402072, im: 0.49162765398743 },
+ FFTComplex{ re: -0.06449863579434, im: 0.03250560813135 },
+ FFTComplex{ re: -0.99575054486311, im: 0.42389784469507 },
+ FFTComplex{ re: -0.65501142790847, im: 0.82546114655624 },
+ FFTComplex{ re: -0.81254441908887, im: -0.51627234660629 },
+ FFTComplex{ re: -0.99646369485481, im: 0.84490533520752 },
+ FFTComplex{ re: 0.00287840603348, im: 0.64768261158166 },
+ FFTComplex{ re: 0.70176989408455, im: -0.20453028573322 },
+ FFTComplex{ re: 0.96361882270190, im: 0.40706967140989 },
+ FFTComplex{ re: -0.68883758192426, im: 0.91338958840772 },
+ FFTComplex{ re: -0.34875585502238, im: 0.71472290693300 },
+ FFTComplex{ re: 0.91980081243087, im: 0.66507455644919 },
+ FFTComplex{ re: -0.99009048343881, im: 0.85868021604848 },
+ FFTComplex{ re: 0.68865791458395, im: 0.55660316809678 },
+ FFTComplex{ re: -0.99484402129368, im: -0.20052559254934 },
+ FFTComplex{ re: 0.94214511408023, im: -0.99696425367461 },
+ FFTComplex{ re: -0.67414626793544, im: 0.49548221180078 },
+ FFTComplex{ re: -0.47339353684664, im: -0.85904328834047 },
+ FFTComplex{ re: 0.14323651387360, im: -0.94145598222488 },
+ FFTComplex{ re: -0.29268293575672, im: 0.05759224927952 },
+ FFTComplex{ re: 0.43793861458754, im: -0.78904969892724 },
+ FFTComplex{ re: -0.36345126374441, im: 0.64874435357162 },
+ FFTComplex{ re: -0.08750604656825, im: 0.97686944362527 },
+ FFTComplex{ re: -0.96495267812511, im: -0.53960305946511 },
+ FFTComplex{ re: 0.55526940659947, im: 0.78891523734774 },
+ FFTComplex{ re: 0.73538215752630, im: 0.96452072373404 },
+ FFTComplex{ re: -0.30889773919437, im: -0.80664389776860 },
+ FFTComplex{ re: 0.03574995626194, im: -0.97325616900959 },
+ FFTComplex{ re: 0.98720684660488, im: 0.48409133691962 },
+ FFTComplex{ re: -0.81689296271203, im: -0.90827703628298 },
+ FFTComplex{ re: 0.67866860118215, im: 0.81284503870856 },
+ FFTComplex{ re: -0.15808569732583, im: 0.85279555024382 },
+ FFTComplex{ re: 0.80723395114371, im: -0.24717418514605 },
+ FFTComplex{ re: 0.47788757329038, im: -0.46333147839295 },
+ FFTComplex{ re: 0.96367554763201, im: 0.38486749303242 },
+ FFTComplex{ re: -0.99143875716818, im: -0.24945277239809 },
+ FFTComplex{ re: 0.83081876925833, im: -0.94780851414763 },
+ FFTComplex{ re: -0.58753191905341, im: 0.01290772389163 },
+ FFTComplex{ re: 0.95538108220960, im: -0.85557052096538 },
+ FFTComplex{ re: -0.96490920476211, im: -0.64020970923102 },
+ FFTComplex{ re: -0.97327101028521, im: 0.12378128133110 },
+ FFTComplex{ re: 0.91400366022124, im: 0.57972471346930 },
+ FFTComplex{ re: -0.99925837363824, im: 0.71084847864067 },
+ FFTComplex{ re: -0.86875903507313, im: -0.20291699203564 },
+ FFTComplex{ re: -0.26240034795124, im: -0.68264554369108 },
+ FFTComplex{ re: -0.24664412953388, im: -0.87642273115183 },
+ FFTComplex{ re: 0.02416275806869, im: 0.27192914288905 },
+ FFTComplex{ re: 0.82068619590515, im: -0.85087787994476 },
+ FFTComplex{ re: 0.88547373760759, im: -0.89636802901469 },
+ FFTComplex{ re: -0.18173078152226, im: -0.26152145156800 },
+ FFTComplex{ re: 0.09355476558534, im: 0.54845123045604 },
+ FFTComplex{ re: -0.54668414224090, im: 0.95980774020221 },
+ FFTComplex{ re: 0.37050990604091, im: -0.59910140383171 },
+ FFTComplex{ re: -0.70373594262891, im: 0.91227665827081 },
+ FFTComplex{ re: -0.34600785879594, im: -0.99441426144200 },
+ FFTComplex{ re: -0.68774481731008, im: -0.30238837956299 },
+ FFTComplex{ re: -0.26843291251234, im: 0.83115668004362 },
+ FFTComplex{ re: 0.49072334613242, im: -0.45359708737775 },
+ FFTComplex{ re: 0.38975993093975, im: 0.95515358099121 },
+ FFTComplex{ re: -0.97757125224150, im: 0.05305894580606 },
+ FFTComplex{ re: -0.17325552859616, im: -0.92770672250494 },
+ FFTComplex{ re: 0.99948035025744, im: 0.58285545563426 },
+ FFTComplex{ re: -0.64946246527458, im: 0.68645507104960 },
+ FFTComplex{ re: -0.12016920576437, im: -0.57147322153312 },
+ FFTComplex{ re: -0.58947456517751, im: -0.34847132454388 },
+ FFTComplex{ re: -0.41815140454465, im: 0.16276422358861 },
+ FFTComplex{ re: 0.99885650204884, im: 0.11136095490444 },
+ FFTComplex{ re: -0.56649614128386, im: -0.90494866361587 },
+ FFTComplex{ re: 0.94138021032330, im: 0.35281916733018 },
+ FFTComplex{ re: -0.75725076534641, im: 0.53650549640587 },
+ FFTComplex{ re: 0.20541973692630, im: -0.94435144369918 },
+ FFTComplex{ re: 0.99980371023351, im: 0.79835913565599 },
+ FFTComplex{ re: 0.29078277605775, im: 0.35393777921520 },
+ FFTComplex{ re: -0.62858772103030, im: 0.38765693387102 },
+ FFTComplex{ re: 0.43440904467688, im: -0.98546330463232 },
+ FFTComplex{ re: -0.98298583762390, im: 0.21021524625209 },
+ FFTComplex{ re: 0.19513029146934, im: -0.94239832251867 },
+ FFTComplex{ re: -0.95476662400101, im: 0.98364554179143 },
+ FFTComplex{ re: 0.93379635304810, im: -0.70881994583682 },
+ FFTComplex{ re: -0.85235410573336, im: -0.08342347966410 },
+ FFTComplex{ re: -0.86425093011245, im: -0.45795025029466 },
+ FFTComplex{ re: 0.38879779059045, im: 0.97274429344593 },
+ FFTComplex{ re: 0.92045124735495, im: -0.62433652524220 },
+ FFTComplex{ re: 0.89162532251878, im: 0.54950955570563 },
+ FFTComplex{ re: -0.36834336949252, im: 0.96458298020975 },
+ FFTComplex{ re: 0.93891760988045, im: -0.89968353740388 },
+ FFTComplex{ re: 0.99267657565094, im: -0.03757034316958 },
+ FFTComplex{ re: -0.94063471614176, im: 0.41332338538963 },
+ FFTComplex{ re: 0.99740224117019, im: -0.16830494996370 },
+ FFTComplex{ re: -0.35899413170555, im: -0.46633226649613 },
+ FFTComplex{ re: 0.05237237274947, im: -0.25640361602661 },
+ FFTComplex{ re: 0.36703583957424, im: -0.38653265641875 },
+ FFTComplex{ re: 0.91653180367913, im: -0.30587628726597 },
+ FFTComplex{ re: 0.69000803499316, im: 0.90952171386132 },
+ FFTComplex{ re: -0.38658751133527, im: 0.99501571208985 },
+ FFTComplex{ re: -0.29250814029851, im: 0.37444994344615 },
+ FFTComplex{ re: -0.60182204677608, im: 0.86779651036123 },
+ FFTComplex{ re: -0.97418588163217, im: 0.96468523666475 },
+ FFTComplex{ re: 0.88461574003963, im: 0.57508405276414 },
+ FFTComplex{ re: 0.05198933055162, im: 0.21269661669964 },
+ FFTComplex{ re: -0.53499621979720, im: 0.97241553731237 },
+ FFTComplex{ re: -0.49429560226497, im: 0.98183865291903 },
+ FFTComplex{ re: -0.98935142339139, im: -0.40249159006933 },
+ FFTComplex{ re: -0.98081380091130, im: -0.72856895534041 },
+ FFTComplex{ re: -0.27338148835532, im: 0.99950922447209 },
+ FFTComplex{ re: 0.06310802338302, im: -0.54539587529618 },
+ FFTComplex{ re: -0.20461677199539, im: -0.14209977628489 },
+ FFTComplex{ re: 0.66223843141647, im: 0.72528579940326 },
+ FFTComplex{ re: -0.84764345483665, im: 0.02372316801261 },
+ FFTComplex{ re: -0.89039863483811, im: 0.88866581484602 },
+ FFTComplex{ re: 0.95903308477986, im: 0.76744927173873 },
+ FFTComplex{ re: 0.73504123909879, im: -0.03747203173192 },
+ FFTComplex{ re: -0.31744434966056, im: -0.36834111883652 },
+ FFTComplex{ re: -0.34110827591623, im: 0.40211222807691 },
+ FFTComplex{ re: 0.47803883714199, im: -0.39423219786288 },
+ FFTComplex{ re: 0.98299195879514, im: 0.01989791390047 },
+ FFTComplex{ re: -0.30963073129751, im: -0.18076720599336 },
+ FFTComplex{ re: 0.99992588229018, im: -0.26281872094289 },
+ FFTComplex{ re: -0.93149731080767, im: -0.98313162570490 },
+ FFTComplex{ re: 0.99923472302773, im: -0.80142993767554 },
+ FFTComplex{ re: -0.26024169633417, im: -0.75999759855752 },
+ FFTComplex{ re: -0.35712514743563, im: 0.19298963768574 },
+ FFTComplex{ re: -0.99899084509530, im: 0.74645156992493 },
+ FFTComplex{ re: 0.86557171579452, im: 0.55593866696299 },
+ FFTComplex{ re: 0.33408042438752, im: 0.86185953874709 },
+ FFTComplex{ re: 0.99010736374716, im: 0.04602397576623 },
+ FFTComplex{ re: -0.66694269691195, im: -0.91643611810148 },
+ FFTComplex{ re: 0.64016792079480, im: 0.15649530836856 },
+ FFTComplex{ re: 0.99570534804836, im: 0.45844586038111 },
+ FFTComplex{ re: -0.63431466947340, im: 0.21079116459234 },
+ FFTComplex{ re: -0.07706847005931, im: -0.89581437101329 },
+ FFTComplex{ re: 0.98590090577724, im: 0.88241721133981 },
+ FFTComplex{ re: 0.80099335254678, im: -0.36851896710853 },
+ FFTComplex{ re: 0.78368131392666, im: 0.45506999802597 },
+ FFTComplex{ re: 0.08707806671691, im: 0.80938994918745 },
+ FFTComplex{ re: -0.86811883080712, im: 0.39347308654705 },
+ FFTComplex{ re: -0.39466529740375, im: -0.66809432114456 },
+ FFTComplex{ re: 0.97875325649683, im: -0.72467840967746 },
+ FFTComplex{ re: -0.95038560288864, im: 0.89563219587625 },
+ FFTComplex{ re: 0.17005239424212, im: 0.54683053962658 },
+ FFTComplex{ re: -0.76910792026848, im: -0.96226617549298 },
+ FFTComplex{ re: 0.99743281016846, im: 0.42697157037567 },
+ FFTComplex{ re: 0.95437383549973, im: 0.97002324109952 },
+ FFTComplex{ re: 0.99578905365569, im: -0.54106826257356 },
+ FFTComplex{ re: 0.28058259829990, im: -0.85361420634036 },
+ FFTComplex{ re: 0.85256524470573, im: -0.64567607735589 },
+ FFTComplex{ re: -0.50608540105128, im: -0.65846015480300 },
+ FFTComplex{ re: -0.97210735183243, im: -0.23095213067791 },
+ FFTComplex{ re: 0.95424048234441, im: -0.99240147091219 },
+ FFTComplex{ re: -0.96926570524023, im: 0.73775654896574 },
+ FFTComplex{ re: 0.30872163214726, im: 0.41514960556126 },
+ FFTComplex{ re: -0.24523839572639, im: 0.63206633394807 },
+ FFTComplex{ re: -0.33813265086024, im: -0.38661779441897 },
+ FFTComplex{ re: -0.05826828420146, im: -0.06940774188029 },
+ FFTComplex{ re: -0.22898461455054, im: 0.97054853316316 },
+ FFTComplex{ re: -0.18509915019881, im: 0.47565762892084 },
+ FFTComplex{ re: -0.10488238045009, im: -0.87769947402394 },
+ FFTComplex{ re: -0.71886586182037, im: 0.78030982480538 },
+ FFTComplex{ re: 0.99793873738654, im: 0.90041310491497 },
+ FFTComplex{ re: 0.57563307626120, im: -0.91034337352097 },
+ FFTComplex{ re: 0.28909646383717, im: 0.96307783970534 },
+ FFTComplex{ re: 0.42188998312520, im: 0.48148651230437 },
+ FFTComplex{ re: 0.93335049681047, im: -0.43537023883588 },
+ FFTComplex{ re: -0.97087374418267, im: 0.86636445711364 },
+ FFTComplex{ re: 0.36722871286923, im: 0.65291654172961 },
+ FFTComplex{ re: -0.81093025665696, im: 0.08778370229363 },
+ FFTComplex{ re: -0.26240603062237, im: -0.92774095379098 },
+ FFTComplex{ re: 0.83996497984604, im: 0.55839849139647 },
+ FFTComplex{ re: -0.99909615720225, im: -0.96024605713970 },
+ FFTComplex{ re: 0.74649464155061, im: 0.12144893606462 },
+ FFTComplex{ re: -0.74774595569805, im: -0.26898062008959 },
+ FFTComplex{ re: 0.95781667469567, im: -0.79047927052628 },
+ FFTComplex{ re: 0.95472308713099, im: -0.08588776019550 },
+ FFTComplex{ re: 0.48708332746299, im: 0.99999041579432 },
+ FFTComplex{ re: 0.46332038247497, im: 0.10964126185063 },
+ FFTComplex{ re: -0.76497004940162, im: 0.89210929242238 },
+ FFTComplex{ re: 0.57397389364339, im: 0.35289703373760 },
+ FFTComplex{ re: 0.75374316974495, im: 0.96705214651335 },
+ FFTComplex{ re: -0.59174397685714, im: -0.89405370422752 },
+ FFTComplex{ re: 0.75087906691890, im: -0.29612672982396 },
+ FFTComplex{ re: -0.98607857336230, im: 0.25034911730023 },
+ FFTComplex{ re: -0.40761056640505, im: -0.90045573444695 },
+ FFTComplex{ re: 0.66929266740477, im: 0.98629493401748 },
+ FFTComplex{ re: -0.97463695257310, im: -0.00190223301301 },
+ FFTComplex{ re: 0.90145509409859, im: 0.99781390365446 },
+ FFTComplex{ re: -0.87259289048043, im: 0.99233587353666 },
+ FFTComplex{ re: -0.91529461447692, im: -0.15698707534206 },
+ FFTComplex{ re: -0.03305738840705, im: -0.37205262859764 },
+ FFTComplex{ re: 0.07223051368337, im: -0.88805001733626 },
+ FFTComplex{ re: 0.99498012188353, im: 0.97094358113387 },
+ FFTComplex{ re: -0.74904939500519, im: 0.99985483641521 },
+ FFTComplex{ re: 0.04585228574211, im: 0.99812337444082 },
+ FFTComplex{ re: -0.89054954257993, im: -0.31791913188064 },
+ FFTComplex{ re: -0.83782144651251, im: 0.97637632547466 },
+ FFTComplex{ re: 0.33454804933804, im: -0.86231516800408 },
+ FFTComplex{ re: -0.99707579362824, im: 0.93237990079441 },
+ FFTComplex{ re: -0.22827527843994, im: 0.18874759397997 },
+ FFTComplex{ re: 0.67248046289143, im: -0.03646211390569 },
+ FFTComplex{ re: -0.05146538187944, im: -0.92599700120679 },
+ FFTComplex{ re: 0.99947295749905, im: 0.93625229707912 },
+ FFTComplex{ re: 0.66951124390363, im: 0.98905825623893 },
+ FFTComplex{ re: -0.99602956559179, im: -0.44654715757688 },
+ FFTComplex{ re: 0.82104905483590, im: 0.99540741724928 },
+ FFTComplex{ re: 0.99186510988782, im: 0.72023001312947 },
+ FFTComplex{ re: -0.65284592392918, im: 0.52186723253637 },
+ FFTComplex{ re: 0.93885443798188, im: -0.74895312615259 },
+ FFTComplex{ re: 0.96735248738388, im: 0.90891816978629 },
+ FFTComplex{ re: -0.22225968841114, im: 0.57124029781228 },
+ FFTComplex{ re: -0.44132783753414, im: -0.92688840659280 },
+ FFTComplex{ re: -0.85694974219574, im: 0.88844532719844 },
+ FFTComplex{ re: 0.91783042091762, im: -0.46356892383970 },
+ FFTComplex{ re: 0.72556974415690, im: -0.99899555770747 },
+ FFTComplex{ re: -0.99711581834508, im: 0.58211560180426 },
+ FFTComplex{ re: 0.77638976371966, im: 0.94321834873819 },
+ FFTComplex{ re: 0.07717324253925, im: 0.58638399856595 },
+ FFTComplex{ re: -0.56049829194163, im: 0.82522301569036 },
+ FFTComplex{ re: 0.98398893639988, im: 0.39467440420569 },
+ FFTComplex{ re: 0.47546946844938, im: 0.68613044836811 },
+ FFTComplex{ re: 0.65675089314631, im: 0.18331637134880 },
+ FFTComplex{ re: 0.03273375457980, im: -0.74933109564108 },
+ FFTComplex{ re: -0.38684144784738, im: 0.51337349030406 },
+ FFTComplex{ re: -0.97346267944545, im: -0.96549364384098 },
+ FFTComplex{ re: -0.53282156061942, im: -0.91423265091354 },
+ FFTComplex{ re: 0.99817310731176, im: 0.61133572482148 },
+ FFTComplex{ re: -0.50254500772635, im: -0.88829338134294 },
+ FFTComplex{ re: 0.01995873238855, im: 0.85223515096765 },
+ FFTComplex{ re: 0.99930381973804, im: 0.94578896296649 },
+ FFTComplex{ re: 0.82907767600783, im: -0.06323442598128 },
+ FFTComplex{ re: -0.58660709669728, im: 0.96840773806582 },
+ FFTComplex{ re: -0.17573736667267, im: -0.48166920859485 },
+ FFTComplex{ re: 0.83434292401346, im: -0.13023450646997 },
+ FFTComplex{ re: 0.05946491307025, im: 0.20511047074866 },
+ FFTComplex{ re: 0.81505484574602, im: -0.94685947861369 },
+ FFTComplex{ re: -0.44976380954860, im: 0.40894572671545 },
+ FFTComplex{ re: -0.89746474625671, im: 0.99846578838537 },
+ FFTComplex{ re: 0.39677256130792, im: -0.74854668609359 },
+ FFTComplex{ re: -0.07588948563079, im: 0.74096214084170 },
+ FFTComplex{ re: 0.76343198951445, im: 0.41746629422634 },
+ FFTComplex{ re: -0.74490104699626, im: 0.94725911744610 },
+ FFTComplex{ re: 0.64880119792759, im: 0.41336660830571 },
+ FFTComplex{ re: 0.62319537462542, im: -0.93098313552599 },
+ FFTComplex{ re: 0.42215817594807, im: -0.07712787385208 },
+ FFTComplex{ re: 0.02704554141885, im: -0.05417518053666 },
+ FFTComplex{ re: 0.80001773566818, im: 0.91542195141039 },
+ FFTComplex{ re: -0.79351832348816, im: -0.36208897989136 },
+ FFTComplex{ re: 0.63872359151636, im: 0.08128252493444 },
+ FFTComplex{ re: 0.52890520960295, im: 0.60048872455592 },
+ FFTComplex{ re: 0.74238552914587, im: 0.04491915291044 },
+ FFTComplex{ re: 0.99096131449250, im: -0.19451182854402 },
+ FFTComplex{ re: -0.80412329643109, im: -0.88513818199457 },
+ FFTComplex{ re: -0.64612616129736, im: 0.72198674804544 },
+ FFTComplex{ re: 0.11657770663191, im: -0.83662833815041 },
+ FFTComplex{ re: -0.95053182488101, im: -0.96939905138082 },
+ FFTComplex{ re: -0.62228872928622, im: 0.82767262846661 },
+ FFTComplex{ re: 0.03004475787316, im: -0.99738896333384 },
+ FFTComplex{ re: -0.97987214341034, im: 0.36526129686425 },
+ FFTComplex{ re: -0.99986980746200, im: -0.36021610299715 },
+ FFTComplex{ re: 0.89110648599879, im: -0.97894250343044 },
+ FFTComplex{ re: 0.10407960510582, im: 0.77357793811619 },
+ FFTComplex{ re: 0.95964737821728, im: -0.35435818285502 },
+ FFTComplex{ re: 0.50843233159162, im: 0.96107691266205 },
+ FFTComplex{ re: 0.17006334670615, im: -0.76854025314829 },
+ FFTComplex{ re: 0.25872675063360, im: 0.99893303933816 },
+ FFTComplex{ re: -0.01115998681937, im: 0.98496019742444 },
+ FFTComplex{ re: -0.79598702973261, im: 0.97138411318894 },
+ FFTComplex{ re: -0.99264708948101, im: -0.99542822402536 },
+ FFTComplex{ re: -0.99829663752818, im: 0.01877138824311 },
+ FFTComplex{ re: -0.70801016548184, im: 0.33680685948117 },
+ FFTComplex{ re: -0.70467057786826, im: 0.93272777501857 },
+ FFTComplex{ re: 0.99846021905254, im: -0.98725746254433 },
+ FFTComplex{ re: -0.63364968534650, im: -0.16473594423746 },
+ FFTComplex{ re: -0.16258217500792, im: -0.95939125400802 },
+ FFTComplex{ re: -0.43645594360633, im: -0.94805030113284 },
+ FFTComplex{ re: -0.99848471702976, im: 0.96245166923809 },
+ FFTComplex{ re: -0.16796458968998, im: -0.98987511890470 },
+ FFTComplex{ re: -0.87979225745213, im: -0.71725725041680 },
+ FFTComplex{ re: 0.44183099021786, im: -0.93568974498761 },
+ FFTComplex{ re: 0.93310180125532, im: -0.99913308068246 },
+ FFTComplex{ re: -0.93941931782002, im: -0.56409379640356 },
+ FFTComplex{ re: -0.88590003188677, im: 0.47624600491382 },
+ FFTComplex{ re: 0.99971463703691, im: -0.83889954253462 },
+ FFTComplex{ re: -0.75376385639978, im: 0.00814643438625 },
+ FFTComplex{ re: 0.93887685615875, im: -0.11284528204636 },
+ FFTComplex{ re: 0.85126435782309, im: 0.52349251543547 },
+ FFTComplex{ re: 0.39701421446381, im: 0.81779634174316 },
+ FFTComplex{ re: -0.37024464187437, im: -0.87071656222959 },
+ FFTComplex{ re: -0.36024828242896, im: 0.34655735648287 },
+ FFTComplex{ re: -0.93388812549209, im: -0.84476541096429 },
+ FFTComplex{ re: -0.65298804552119, im: -0.18439575450921 },
+ FFTComplex{ re: 0.11960319006843, im: 0.99899346780168 },
+ FFTComplex{ re: 0.94292565553160, im: 0.83163906518293 },
+ FFTComplex{ re: 0.75081145286948, im: -0.35533223142265 },
+ FFTComplex{ re: 0.56721979748394, im: -0.24076836414499 },
+ FFTComplex{ re: 0.46857766746029, im: -0.30140233457198 },
+ FFTComplex{ re: 0.97312313923635, im: -0.99548191630031 },
+ FFTComplex{ re: -0.38299976567017, im: 0.98516909715427 },
+ FFTComplex{ re: 0.41025800019463, im: 0.02116736935734 },
+ FFTComplex{ re: 0.09638062008048, im: 0.04411984381457 },
+ FFTComplex{ re: -0.85283249275397, im: 0.91475563922421 },
+ FFTComplex{ re: 0.88866808958124, im: -0.99735267083226 },
+ FFTComplex{ re: -0.48202429536989, im: -0.96805608884164 },
+ FFTComplex{ re: 0.27572582416567, im: 0.58634753335832 },
+ FFTComplex{ re: -0.65889129659168, im: 0.58835634138583 },
+ FFTComplex{ re: 0.98838086953732, im: 0.99994349600236 },
+ FFTComplex{ re: -0.20651349620689, im: 0.54593044066355 },
+ FFTComplex{ re: -0.62126416356920, im: -0.59893681700392 },
+ FFTComplex{ re: 0.20320105410437, im: -0.86879180355289 },
+ FFTComplex{ re: -0.97790548600584, im: 0.96290806999242 },
+ FFTComplex{ re: 0.11112534735126, im: 0.21484763313301 },
+ FFTComplex{ re: -0.41368337314182, im: 0.28216837680365 },
+ FFTComplex{ re: 0.24133038992960, im: 0.51294362630238 },
+ FFTComplex{ re: -0.66393410674885, im: -0.08249679629081 },
+ FFTComplex{ re: -0.53697829178752, im: -0.97649903936228 },
+ FFTComplex{ re: -0.97224737889348, im: 0.22081333579837 },
+ FFTComplex{ re: 0.87392477144549, im: -0.12796173740361 },
+ FFTComplex{ re: 0.19050361015753, im: 0.01602615387195 },
+ FFTComplex{ re: -0.46353441212724, im: -0.95249041539006 },
+ FFTComplex{ re: -0.07064096339021, im: -0.94479803205886 },
+ FFTComplex{ re: -0.92444085484466, im: -0.10457590187436 },
+ FFTComplex{ re: -0.83822593578728, im: -0.01695043208885 },
+ FFTComplex{ re: 0.75214681811150, im: -0.99955681042665 },
+ FFTComplex{ re: -0.42102998829339, im: 0.99720941999394 },
+ FFTComplex{ re: -0.72094786237696, im: -0.35008961934255 },
+ FFTComplex{ re: 0.78843311019251, im: 0.52851398958271 },
+ FFTComplex{ re: 0.97394027897442, im: -0.26695944086561 },
+ FFTComplex{ re: 0.99206463477946, im: -0.57010120849429 },
+ FFTComplex{ re: 0.76789609461795, im: -0.76519356730966 },
+ FFTComplex{ re: -0.82002421836409, im: -0.73530179553767 },
+ FFTComplex{ re: 0.81924990025724, im: 0.99698425250579 },
+ FFTComplex{ re: -0.26719850873357, im: 0.68903369776193 },
+ FFTComplex{ re: -0.43311260380975, im: 0.85321815947490 },
+ FFTComplex{ re: 0.99194979673836, im: 0.91876249766422 },
+ FFTComplex{ re: -0.80692001248487, im: -0.32627540663214 },
+ FFTComplex{ re: 0.43080003649976, im: -0.21919095636638 },
+ FFTComplex{ re: 0.67709491937357, im: -0.95478075822906 },
+ FFTComplex{ re: 0.56151770568316, im: -0.70693811747778 },
+ FFTComplex{ re: 0.10831862810749, im: -0.08628837174592 },
+ FFTComplex{ re: 0.91229417540436, im: -0.65987351408410 },
+ FFTComplex{ re: -0.48972893932274, im: 0.56289246362686 },
+ FFTComplex{ re: -0.89033658689697, im: -0.71656563987082 },
+ FFTComplex{ re: 0.65269447475094, im: 0.65916004833932 },
+ FFTComplex{ re: 0.67439478141121, im: -0.81684380846796 },
+ FFTComplex{ re: -0.47770832416973, im: -0.16789556203025 },
+ FFTComplex{ re: -0.99715979260878, im: -0.93565784007648 },
+ FFTComplex{ re: -0.90889593602546, im: 0.62034397054380 },
+ FFTComplex{ re: -0.06618622548177, im: -0.23812217221359 },
+ FFTComplex{ re: 0.99430266919728, im: 0.18812555317553 },
+ FFTComplex{ re: 0.97686402381843, im: -0.28664534366620 },
+ FFTComplex{ re: 0.94813650221268, im: -0.97506640027128 },
+ FFTComplex{ re: -0.95434497492853, im: -0.79607978501983 },
+ FFTComplex{ re: -0.49104783137150, im: 0.32895214359663 },
+ FFTComplex{ re: 0.99881175120751, im: 0.88993983831354 },
+ FFTComplex{ re: 0.50449166760303, im: -0.85995072408434 },
+ FFTComplex{ re: 0.47162891065108, im: -0.18680204049569 },
+ FFTComplex{ re: -0.62081581361840, im: 0.75000676218956 },
+ FFTComplex{ re: -0.43867015250812, im: 0.99998069244322 },
+ FFTComplex{ re: 0.98630563232075, im: -0.53578899600662 },
+ FFTComplex{ re: -0.61510362277374, im: -0.89515019899997 },
+ FFTComplex{ re: -0.03841517601843, im: -0.69888815681179 },
+ FFTComplex{ re: -0.30102157304644, im: -0.07667808922205 },
+ FFTComplex{ re: 0.41881284182683, im: 0.02188098922282 },
+ FFTComplex{ re: -0.86135454941237, im: 0.98947480909359 },
+ FFTComplex{ re: 0.67226861393788, im: -0.13494389011014 },
+ FFTComplex{ re: -0.70737398842068, im: -0.76547349325992 },
+ FFTComplex{ re: 0.94044946687963, im: 0.09026201157416 },
+ FFTComplex{ re: -0.82386352534327, im: 0.08924768823676 },
+ FFTComplex{ re: -0.32070666698656, im: 0.50143421908753 },
+ FFTComplex{ re: 0.57593163224487, im: -0.98966422921509 },
+ FFTComplex{ re: -0.36326018419965, im: 0.07440243123228 },
+ FFTComplex{ re: 0.99979044674350, im: -0.14130287347405 },
+ FFTComplex{ re: -0.92366023326932, im: -0.97979298068180 },
+ FFTComplex{ re: -0.44607178518598, im: -0.54233252016394 },
+ FFTComplex{ re: 0.44226800932956, im: 0.71326756742752 },
+ FFTComplex{ re: 0.03671907158312, im: 0.63606389366675 },
+ FFTComplex{ re: 0.52175424682195, im: -0.85396826735705 },
+ FFTComplex{ re: -0.94701139690956, im: -0.01826348194255 },
+ FFTComplex{ re: -0.98759606946049, im: 0.82288714303073 },
+ FFTComplex{ re: 0.87434794743625, im: 0.89399495655433 },
+ FFTComplex{ re: -0.93412041758744, im: 0.41374052024363 },
+ FFTComplex{ re: 0.96063943315511, im: 0.93116709541280 },
+ FFTComplex{ re: 0.97534253457837, im: 0.86150930812689 },
+ FFTComplex{ re: 0.99642466504163, im: 0.70190043427512 },
+ FFTComplex{ re: -0.94705089665984, im: -0.29580042814306 },
+ FFTComplex{ re: 0.91599807087376, im: -0.98147830385781 },
+];
}
#[cfg(feature="decoder_aac")]
+#[allow(clippy::comparison_chain)]
+#[allow(clippy::excessive_precision)]
#[allow(clippy::manual_memcpy)]
#[allow(clippy::useless_let_if_seq)]
mod aac;
extern crate nihav_codec_support;
#[cfg(feature="decoders")]
+#[allow(clippy::collapsible_if)]
#[allow(clippy::needless_range_loop)]
mod codecs;