symphonia-bundle-mp3-0.5.2/.cargo_vcs_info.json0000644000000001620000000000100150120ustar { "git": { "sha1": "412f44daab39920beeb81d78b0e4271b263d33e9" }, "path_in_vcs": "symphonia-bundle-mp3" }symphonia-bundle-mp3-0.5.2/Cargo.toml0000644000000025000000000000100130060ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2018" rust-version = "1.53" name = "symphonia-bundle-mp3" version = "0.5.2" authors = ["Philip Deljanov "] description = "Pure Rust MP1, MP2, and MP3 demuxer and decoder (a part of project Symphonia)." homepage = "https://github.com/pdeljanov/Symphonia" readme = "README.md" keywords = [ "audio", "codec", "decoder", "mp3", "mpeg", ] categories = [ "multimedia", "multimedia::audio", "multimedia::encoding", ] license = "MPL-2.0" repository = "https://github.com/pdeljanov/Symphonia" [dependencies.bitflags] version = "1.2.1" [dependencies.lazy_static] version = "1.4.0" [dependencies.log] version = "0.4" [dependencies.symphonia-core] version = "0.5.2" [dependencies.symphonia-metadata] version = "0.5.2" [features] default = [ "mp1", "mp2", "mp3", ] mp1 = [] mp2 = [] mp3 = [] symphonia-bundle-mp3-0.5.2/Cargo.toml.orig000064400000000000000000000014471046102023000165000ustar 00000000000000[package] name = "symphonia-bundle-mp3" version = "0.5.2" description = "Pure Rust MP1, MP2, and MP3 demuxer and decoder (a part of project Symphonia)." homepage = "https://github.com/pdeljanov/Symphonia" repository = "https://github.com/pdeljanov/Symphonia" authors = ["Philip Deljanov "] license = "MPL-2.0" readme = "README.md" categories = ["multimedia", "multimedia::audio", "multimedia::encoding"] keywords = ["audio", "codec", "decoder", "mp3", "mpeg"] edition = "2018" rust-version = "1.53" [features] default = ["mp1", "mp2", "mp3"] mp1 = [] mp2 = [] mp3 = [] [dependencies] log = "0.4" bitflags = "1.2.1" lazy_static = "1.4.0" symphonia-core = { version = "0.5.2", path = "../symphonia-core" } symphonia-metadata = { version = "0.5.2", path = "../symphonia-metadata" }symphonia-bundle-mp3-0.5.2/README.md000064400000000000000000000020641046102023000150640ustar 00000000000000# Symphonia MP3 (and MP1, MP2) Codec [![Docs](https://docs.rs/symphonia-bundle-mp3/badge.svg)](https://docs.rs/symphonia-bundle-mp3) MPEG-1 and MPEG-2 Layer I, II, III (MP1, MP2, MP3) decoder for Project Symphonia. **Note:** This crate is part of Symphonia. Please use the [`symphonia`](https://crates.io/crates/symphonia) crate instead of this one directly. ## Support This decoder implements Layer I, II, III of MPEG-1 Part 3 (ISO/IEC 11172-3), and all the extensions and enhancements defined in MPEG-2 Part 3 (ISO/IEC 13818-3). ## Conformance The decoder will ideally conform to ISO/IEC 11172-4 and ISO/IEC 13818-4. ## License Symphonia is provided under the MPL v2.0 license. Please refer to the LICENSE file for more details. ## Contributing Symphonia is an open-source project and contributions are very welcome! If you would like to make a large contribution, please raise an issue ahead of time to make sure your efforts fit into the project goals, and that no duplication of efforts occurs. All contributors will be credited within the CONTRIBUTORS file. symphonia-bundle-mp3-0.5.2/src/common.rs000064400000000000000000000123621046102023000162340ustar 00000000000000// Symphonia // Copyright (c) 2019-2022 The Project Symphonia Developers. // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. use symphonia_core::audio::{AudioBuffer, Channels, Layout, SignalSpec}; use symphonia_core::codecs::{CodecType, CODEC_TYPE_MP1, CODEC_TYPE_MP2, CODEC_TYPE_MP3}; use symphonia_core::errors::Result; use symphonia_core::io::BufReader; /// The MPEG audio version. #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum MpegVersion { /// Version 2.5 Mpeg2p5, /// Version 2 Mpeg2, /// Version 1 Mpeg1, } /// The MPEG audio layer. #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum MpegLayer { /// Layer 1 Layer1, /// Layer 2 Layer2, /// Layer 3 Layer3, } /// For Joint Stereo channel mode, the mode extension describes the features and parameters of the /// stereo encoding. #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Mode { /// Joint Stereo in layer 3 may use both Mid-Side and Intensity encoding. Layer3 { mid_side: bool, intensity: bool }, /// Joint Stereo in layers 1 and 2 may only use Intensity encoding on a set of bands. The range /// of bands using intensity encoding is `bound..32`. Intensity { bound: u32 }, } /// The channel mode. #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum ChannelMode { /// Single mono audio channel. Mono, /// Dual mono audio channels. DualMono, /// Stereo channels. Stereo, /// Joint Stereo encoded channels (decodes to Stereo). JointStereo(Mode), } impl ChannelMode { /// Gets the number of channels. #[inline(always)] pub fn count(&self) -> usize { match self { ChannelMode::Mono => 1, _ => 2, } } /// Gets the the channel map. #[inline(always)] pub fn channels(&self) -> Channels { match self { ChannelMode::Mono => Channels::FRONT_LEFT, _ => Channels::FRONT_LEFT | Channels::FRONT_RIGHT, } } } /// The emphasis applied during encoding. #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Emphasis { /// No emphasis None, /// 50/15us Fifty15, /// CCIT J.17 CcitJ17, } /// A MPEG 1, 2, or 2.5 audio frame header. #[derive(Debug)] pub struct FrameHeader { pub version: MpegVersion, pub layer: MpegLayer, pub bitrate: u32, pub sample_rate: u32, pub sample_rate_idx: usize, pub channel_mode: ChannelMode, pub emphasis: Emphasis, pub is_copyrighted: bool, pub is_original: bool, pub has_padding: bool, pub has_crc: bool, pub frame_size: usize, } impl FrameHeader { /// Returns true if this a MPEG1 frame, false otherwise. #[inline(always)] pub fn is_mpeg1(&self) -> bool { self.version == MpegVersion::Mpeg1 } /// Returns true if this a MPEG2.5 frame, false otherwise. #[inline(always)] #[allow(dead_code)] pub fn is_mpeg2p5(&self) -> bool { self.version == MpegVersion::Mpeg2p5 } /// Returns the codec type for the frame. pub fn codec(&self) -> CodecType { match self.layer { MpegLayer::Layer1 => CODEC_TYPE_MP1, MpegLayer::Layer2 => CODEC_TYPE_MP2, MpegLayer::Layer3 => CODEC_TYPE_MP3, } } /// Returns a signal specification for the frame. #[allow(dead_code)] pub fn spec(&self) -> SignalSpec { let layout = match self.n_channels() { 1 => Layout::Mono, 2 => Layout::Stereo, _ => unreachable!(), }; SignalSpec::new_with_layout(self.sample_rate, layout) } /// Returns the number of audio samples in the frame per channel. pub fn duration(&self) -> u64 { match self.layer { MpegLayer::Layer1 => 384, MpegLayer::Layer2 => 1152, MpegLayer::Layer3 => 576 * self.n_granules() as u64, } } /// Returns the number of granules in the frame. #[inline(always)] pub fn n_granules(&self) -> usize { match self.version { MpegVersion::Mpeg1 => 2, _ => 1, } } /// Returns the number of channels per granule. #[inline(always)] pub fn n_channels(&self) -> usize { self.channel_mode.count() } /// Returns true if Intensity Stereo encoding is used, false otherwise. #[allow(dead_code)] #[inline(always)] pub fn is_intensity_stereo(&self) -> bool { match self.channel_mode { ChannelMode::JointStereo(Mode::Intensity { .. }) => true, ChannelMode::JointStereo(Mode::Layer3 { intensity, .. }) => intensity, _ => false, } } /// Get the side information length. #[inline(always)] pub fn side_info_len(&self) -> usize { match (self.version, self.channel_mode) { (MpegVersion::Mpeg1, ChannelMode::Mono) => 17, (MpegVersion::Mpeg1, _) => 32, (_, ChannelMode::Mono) => 9, (_, _) => 17, } } } pub trait Layer { fn decode( &mut self, reader: &mut BufReader<'_>, header: &FrameHeader, out: &mut AudioBuffer, ) -> Result<()>; } symphonia-bundle-mp3-0.5.2/src/decoder.rs000064400000000000000000000125751046102023000163570ustar 00000000000000// Symphonia // Copyright (c) 2019-2022 The Project Symphonia Developers. // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. use symphonia_core::audio::{AsAudioBufferRef, AudioBuffer, AudioBufferRef, Signal}; use symphonia_core::codecs::{CodecDescriptor, CodecParameters, CodecType}; use symphonia_core::codecs::{Decoder, DecoderOptions, FinalizeResult}; use symphonia_core::errors::{decode_error, unsupported_error, Result}; use symphonia_core::formats::Packet; use symphonia_core::io::FiniteStream; use symphonia_core::support_codec; #[cfg(feature = "mp1")] use symphonia_core::codecs::CODEC_TYPE_MP1; #[cfg(feature = "mp2")] use symphonia_core::codecs::CODEC_TYPE_MP2; #[cfg(feature = "mp3")] use symphonia_core::codecs::CODEC_TYPE_MP3; use super::{common::*, header}; #[cfg(feature = "mp1")] use crate::layer1; #[cfg(feature = "mp2")] use crate::layer2; #[cfg(feature = "mp3")] use crate::layer3; enum State { #[cfg(feature = "mp1")] Layer1(layer1::Layer1), #[cfg(feature = "mp2")] Layer2(layer2::Layer2), #[cfg(feature = "mp3")] Layer3(Box), } impl State { fn new(codec: CodecType) -> Self { match codec { #[cfg(feature = "mp1")] CODEC_TYPE_MP1 => State::Layer1(layer1::Layer1::new()), #[cfg(feature = "mp2")] CODEC_TYPE_MP2 => State::Layer2(layer2::Layer2::new()), #[cfg(feature = "mp3")] CODEC_TYPE_MP3 => State::Layer3(Box::new(layer3::Layer3::new())), _ => unreachable!(), } } } /// MPEG1 and MPEG2 audio layer 1, 2, and 3 decoder. pub struct MpaDecoder { params: CodecParameters, state: State, buf: AudioBuffer, } impl MpaDecoder { fn decode_inner(&mut self, packet: &Packet) -> Result<()> { let mut reader = packet.as_buf_reader(); let header = header::read_frame_header(&mut reader)?; // The packet should be the size stated in the header. if header.frame_size != reader.bytes_available() as usize { return decode_error("mpa: invalid packet length"); } // The audio buffer can only be created after the first frame is decoded. if self.buf.is_unused() { self.buf = AudioBuffer::new(1152, header.spec()); } else { // Ensure the packet contains an audio frame with the same signal specification as the // buffer. // // TODO: Is it worth it to support changing signal specifications? if self.buf.spec() != &header.spec() { return decode_error("mpa: invalid audio buffer signal spec for packet"); } } // Clear the audio buffer. self.buf.clear(); // Choose the decode step based on the MPEG layer and the current codec type. match &mut self.state { #[cfg(feature = "mp1")] State::Layer1(layer) if header.layer == MpegLayer::Layer1 => { layer.decode(&mut reader, &header, &mut self.buf)?; } #[cfg(feature = "mp2")] State::Layer2(layer) if header.layer == MpegLayer::Layer2 => { layer.decode(&mut reader, &header, &mut self.buf)?; } #[cfg(feature = "mp3")] State::Layer3(layer) if header.layer == MpegLayer::Layer3 => { layer.decode(&mut reader, &header, &mut self.buf)?; } _ => return decode_error("mpa: invalid mpeg audio layer"), } self.buf.trim(packet.trim_start() as usize, packet.trim_end() as usize); Ok(()) } } impl Decoder for MpaDecoder { fn try_new(params: &CodecParameters, _: &DecoderOptions) -> Result { // This decoder only supports MP1, MP2, and MP3. match params.codec { #[cfg(feature = "mp1")] CODEC_TYPE_MP1 => (), #[cfg(feature = "mp2")] CODEC_TYPE_MP2 => (), #[cfg(feature = "mp3")] CODEC_TYPE_MP3 => (), _ => return unsupported_error("mpa: invalid codec type"), } // Create decoder state. let state = State::new(params.codec); Ok(MpaDecoder { params: params.clone(), state, buf: AudioBuffer::unused() }) } fn supported_codecs() -> &'static [CodecDescriptor] { &[ #[cfg(feature = "mp1")] support_codec!(CODEC_TYPE_MP1, "mp1", "MPEG Audio Layer 1"), #[cfg(feature = "mp2")] support_codec!(CODEC_TYPE_MP2, "mp2", "MPEG Audio Layer 2"), #[cfg(feature = "mp3")] support_codec!(CODEC_TYPE_MP3, "mp3", "MPEG Audio Layer 3"), ] } fn codec_params(&self) -> &CodecParameters { &self.params } fn reset(&mut self) { // Fully reset the decoder state. self.state = State::new(self.params.codec); } fn decode(&mut self, packet: &Packet) -> Result> { if let Err(e) = self.decode_inner(packet) { self.buf.clear(); Err(e) } else { Ok(self.buf.as_audio_buffer_ref()) } } fn finalize(&mut self) -> FinalizeResult { Default::default() } fn last_decoded(&self) -> AudioBufferRef<'_> { self.buf.as_audio_buffer_ref() } } symphonia-bundle-mp3-0.5.2/src/demuxer.rs000064400000000000000000001004641046102023000164160ustar 00000000000000// Symphonia // Copyright (c) 2019-2022 The Project Symphonia Developers. // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. use symphonia_core::support_format; use symphonia_core::checksum::Crc16AnsiLe; use symphonia_core::codecs::CodecParameters; use symphonia_core::errors::{seek_error, Result, SeekErrorKind}; use symphonia_core::formats::prelude::*; use symphonia_core::io::*; use symphonia_core::meta::{Metadata, MetadataLog}; use symphonia_core::probe::{Descriptor, Instantiate, QueryDescriptor}; use crate::common::{FrameHeader, MpegLayer}; use crate::header::{self, MAX_MPEG_FRAME_SIZE, MPEG_HEADER_LEN}; use std::io::{Seek, SeekFrom}; use log::{debug, info, warn}; /// MPEG1 and MPEG2 audio elementary stream reader. /// /// `MpaReader` implements a demuxer for the MPEG1 and MPEG2 audio elementary stream. pub struct MpaReader { reader: MediaSourceStream, tracks: Vec, cues: Vec, metadata: MetadataLog, options: FormatOptions, first_packet_pos: u64, next_packet_ts: u64, } impl QueryDescriptor for MpaReader { fn query() -> &'static [Descriptor] { &[ // Layer 1 support_format!( "mp1", "MPEG Audio Layer 1 Native", &["mp1"], &["audio/mpeg", "audio/mp1"], &[ &[0xff, 0xfe], // MPEG 1 with CRC &[0xff, 0xff], // MPEG 1 &[0xff, 0xf6], // MPEG 2 with CRC &[0xff, 0xf7], // MPEG 2 &[0xff, 0xe6], // MPEG 2.5 with CRC &[0xff, 0xe7], // MPEG 2.5 ] ), // Layer 2 support_format!( "mp2", "MPEG Audio Layer 2 Native", &["mp2"], &["audio/mpeg", "audio/mp2"], &[ &[0xff, 0xfc], // MPEG 1 with CRC &[0xff, 0xfd], // MPEG 1 &[0xff, 0xf4], // MPEG 2 with CRC &[0xff, 0xf5], // MPEG 2 &[0xff, 0xe4], // MPEG 2.5 with CRC &[0xff, 0xe5], // MPEG 2.5 ] ), // Layer 3 support_format!( "mp3", "MPEG Audio Layer 3 Native", &["mp3"], &["audio/mpeg", "audio/mp3"], &[ &[0xff, 0xfa], // MPEG 1 with CRC &[0xff, 0xfb], // MPEG 1 &[0xff, 0xf2], // MPEG 2 with CRC &[0xff, 0xf3], // MPEG 2 &[0xff, 0xe2], // MPEG 2.5 with CRC &[0xff, 0xe3], // MPEG 2.5 ] ), ] } fn score(_context: &[u8]) -> u8 { 255 } } impl FormatReader for MpaReader { fn try_new(mut source: MediaSourceStream, options: &FormatOptions) -> Result { // Try to read the first MPEG frame. let (header, packet) = read_mpeg_frame_strict(&mut source)?; // Use the header to populate the codec parameters. let mut params = CodecParameters::new(); params .for_codec(header.codec()) .with_sample_rate(header.sample_rate) .with_time_base(TimeBase::new(1, header.sample_rate)) .with_channels(header.channel_mode.channels()); // Check if there is a Xing/Info tag contained in the first frame. if let Some(info_tag) = try_read_info_tag(&packet, &header) { // The LAME tag contains ReplayGain and padding information. let (delay, padding) = if let Some(lame_tag) = info_tag.lame { params.with_delay(lame_tag.enc_delay).with_padding(lame_tag.enc_padding); (lame_tag.enc_delay, lame_tag.enc_padding) } else { (0, 0) }; // The base Xing/Info tag may contain the number of frames. if let Some(num_mpeg_frames) = info_tag.num_frames { info!("using xing header for duration"); let num_frames = u64::from(num_mpeg_frames) * header.duration(); // Adjust for gapless playback. if options.enable_gapless { params.with_n_frames(num_frames - u64::from(delay) - u64::from(padding)); } else { params.with_n_frames(num_frames); } } } else if let Some(vbri_tag) = try_read_vbri_tag(&packet, &header) { info!("using vbri header for duration"); let num_frames = u64::from(vbri_tag.num_mpeg_frames) * header.duration(); // Check if there is a VBRI tag. params.with_n_frames(num_frames); } else { // The first frame was not a Xing/Info header, rewind back to the start of the frame so // that it may be decoded. source.seek_buffered_rev(MPEG_HEADER_LEN + header.frame_size); // Likely not a VBR file, so estimate the duration if seekable. if source.is_seekable() { info!("estimating duration from bitrate, may be inaccurate for vbr files"); if let Some(n_mpeg_frames) = estimate_num_mpeg_frames(&mut source) { params.with_n_frames(n_mpeg_frames * header.duration()); } } } let first_packet_pos = source.pos(); Ok(MpaReader { reader: source, tracks: vec![Track::new(0, params)], cues: Vec::new(), metadata: Default::default(), options: *options, first_packet_pos, next_packet_ts: 0, }) } fn next_packet(&mut self) -> Result { let (header, packet) = loop { // Read the next MPEG frame. let (header, packet) = read_mpeg_frame(&mut self.reader)?; // Check if the packet contains a Xing, Info, or VBRI tag. if is_maybe_info_tag(&packet, &header) { if try_read_info_tag(&packet, &header).is_some() { // Discard the packet and tag since it was not at the start of the stream. warn!("found an unexpected xing tag, discarding"); continue; } } else if is_maybe_vbri_tag(&packet, &header) && try_read_vbri_tag(&packet, &header).is_some() { // Discard the packet and tag since it was not at the start of the stream. warn!("found an unexpected vbri tag, discarding"); continue; } break (header, packet); }; // Each frame contains 1 or 2 granules with each granule being exactly 576 samples long. let ts = self.next_packet_ts; let duration = header.duration(); self.next_packet_ts += duration; let mut packet = Packet::new_from_boxed_slice(0, ts, duration, packet.into_boxed_slice()); if self.options.enable_gapless { symphonia_core::formats::util::trim_packet( &mut packet, self.tracks[0].codec_params.delay.unwrap_or(0), self.tracks[0].codec_params.n_frames, ); } Ok(packet) } fn metadata(&mut self) -> Metadata<'_> { self.metadata.metadata() } fn cues(&self) -> &[Cue] { &self.cues } fn tracks(&self) -> &[Track] { &self.tracks } fn seek(&mut self, mode: SeekMode, to: SeekTo) -> Result { const MAX_REF_FRAMES: usize = 4; const REF_FRAMES_MASK: usize = MAX_REF_FRAMES - 1; // Get the timestamp of the desired audio frame. let desired_ts = match to { // Frame timestamp given. SeekTo::TimeStamp { ts, .. } => ts, // Time value given, calculate frame timestamp from sample rate. SeekTo::Time { time, .. } => { // Use the sample rate to calculate the frame timestamp. If sample rate is not // known, the seek cannot be completed. if let Some(sample_rate) = self.tracks[0].codec_params.sample_rate { TimeBase::new(1, sample_rate).calc_timestamp(time) } else { return seek_error(SeekErrorKind::Unseekable); } } }; // If gapless playback is enabled, get the delay. let delay = if self.options.enable_gapless { u64::from(self.tracks[0].codec_params.delay.unwrap_or(0)) } else { 0 }; // The required timestamp is offset by the delay. let required_ts = desired_ts + delay; // If the stream is unseekable and the required timestamp in the past, then return an // error, it is not possible to seek to it. let is_seekable = self.reader.is_seekable(); if !is_seekable && required_ts < self.next_packet_ts { return seek_error(SeekErrorKind::ForwardOnly); } debug!("seeking to ts={} (+{} delay = {})", desired_ts, delay, required_ts); // Step 1 // // In coarse seek mode, the underlying media source stream will be roughly seeked based on // the required timestamp and the total duration of the media. Coarse seek mode requires a // seekable stream because the total length in bytes of the stream is required. // // In accurate seek mode, the underlying media source stream will not be seeked unless the // required timestamp is in the past, in which case the stream is seeked back to the start. match mode { SeekMode::Coarse if is_seekable => self.preseek_coarse(required_ts, delay)?, SeekMode::Accurate => self.preseek_accurate(required_ts)?, _ => (), }; // Step 2 // // Following the pre-seek operation above, parse MPEG frames (packets) one-by-one from the // current position in the stream until the frame containing the desired timestamp is // reached. For coarse seeks, this should only parse a few packets. For accurate seeks, the // entire stream could potentially be parsed. let mut frames: [FramePos; MAX_REF_FRAMES] = Default::default(); let mut n_parsed = 0; loop { // Parse the next frame header. let header = header::parse_frame_header(header::sync_frame(&mut self.reader)?)?; // Position of the frame header. let pos = self.reader.pos() - std::mem::size_of::() as u64; // Calculate the duration of the frame. let duration = header.duration(); // Add the frame to the frame ring. frames[n_parsed & REF_FRAMES_MASK] = FramePos { pos, ts: self.next_packet_ts }; n_parsed += 1; // If the next frame's timestamp would exceed the desired timestamp, rewind back to the // start of this frame and end the search. if self.next_packet_ts + duration > required_ts { // The main_data_begin offset is a negative offset from the frame's header to where // its main data begins. Therefore, for a decoder to properly decode this frame, the // reader must provide previous (reference) frames up-to and including the frame // that contains the first byte this frame's main_data. let main_data_begin = read_main_data_begin(&mut self.reader, &header)? as u64; debug!( "found frame with ts={} ({}) @ pos={} with main_data_begin={}", self.next_packet_ts.saturating_sub(delay), self.next_packet_ts, pos, main_data_begin ); // The number of reference frames is 0 if main_data_begin is also 0. Otherwise, // attempt to find the first (oldest) reference frame, then select 1 frame before // that one to actually seek to. let mut n_ref_frames = 0; let mut ref_frame = &frames[(n_parsed - 1) & REF_FRAMES_MASK]; if main_data_begin > 0 { // The maximum number of reference frames is limited to the number of frames // read and the number of previous frames recorded. let max_ref_frames = std::cmp::min(n_parsed, frames.len()); while n_ref_frames < max_ref_frames { ref_frame = &frames[(n_parsed - n_ref_frames - 1) & REF_FRAMES_MASK]; if pos - ref_frame.pos >= main_data_begin { break; } n_ref_frames += 1; } debug!( "will seek -{} frame(s) to ts={} ({}) @ pos={} (-{} bytes)", n_ref_frames, ref_frame.ts.saturating_sub(delay), ref_frame.ts, ref_frame.pos, pos - ref_frame.pos ); } // Do the actual seek to the reference frame. self.next_packet_ts = ref_frame.ts; self.reader.seek_buffered(ref_frame.pos); break; } // Otherwise, ignore the frame body. self.reader.ignore_bytes(header.frame_size as u64)?; // Increment the timestamp for the next packet. self.next_packet_ts += duration; } let actual_ts = self.next_packet_ts.saturating_sub(delay); debug!( "seeked to ts={} ({}) (delta={})", actual_ts, self.next_packet_ts, self.next_packet_ts as i64 - required_ts as i64, ); Ok(SeekedTo { track_id: 0, required_ts: required_ts - delay, actual_ts }) } fn into_inner(self: Box) -> MediaSourceStream { self.reader } } impl MpaReader { /// Seeks the media source stream to a byte position roughly where the packet with the required /// timestamp should be located. fn preseek_coarse(&mut self, required_ts: u64, delay: u64) -> Result<()> { // If gapless playback is enabled, get the padding. let padding = if self.options.enable_gapless { u64::from(self.tracks[0].codec_params.padding.unwrap_or(0)) } else { 0 }; // Get the total byte length of the stream. It is not possible to seek without this. let total_byte_len = match self.reader.byte_len() { Some(byte_len) => byte_len, None => return seek_error(SeekErrorKind::Unseekable), }; // Get the total duration in audio frames of the stream, including delay and padding. It is // not possible to seek without this. let duration = match self.tracks[0].codec_params.n_frames { Some(num_frames) => num_frames + delay + padding, None => return seek_error(SeekErrorKind::Unseekable), }; // Calculate the total size of the audio data. let audio_byte_len = total_byte_len - self.first_packet_pos; // Calculate, roughly, where the packet containing the required timestamp is in the media // source stream relative to the start of the audio data. let packet_pos = ((u128::from(required_ts) * u128::from(audio_byte_len)) / u128::from(duration)) as u64; // It is preferable to return a packet with a timestamp before the requested timestamp. // Therefore, subtract the maximum packet size from the position found above to ensure this. let seek_pos = packet_pos.saturating_sub(MAX_MPEG_FRAME_SIZE) + self.first_packet_pos; // Seek the media source stream. self.reader.seek(SeekFrom::Start(seek_pos))?; // Resync to the start of the next packet. let (header, _) = read_mpeg_frame_strict(&mut self.reader)?; // Calculate, roughly, the timestamp of the packet based on the byte position after resync. let seeked_pos = self.reader.pos(); let ts = ((u128::from(seeked_pos - self.first_packet_pos) * u128::from(duration)) / u128::from(audio_byte_len)) as u64; // Assuming the duration of a packet remains constant throughout the stream (not a // guarantee, but usually the case), round the timestamp to a multiple of a packet duration. let packet_dur = header.duration(); self.next_packet_ts = (ts / packet_dur) * packet_dur; Ok(()) } /// Seeks the media source stream back to the start of the first packet if the required /// timestamp is in the past. fn preseek_accurate(&mut self, required_ts: u64) -> Result<()> { if required_ts < self.next_packet_ts { let seeked_pos = self.reader.seek(SeekFrom::Start(self.first_packet_pos))?; // Since the elementary stream has no timestamp information, the position seeked // to must be exactly as requested. if seeked_pos != self.first_packet_pos { return seek_error(SeekErrorKind::Unseekable); } // Successfuly seeked to the start of the stream, reset the next packet timestamp. self.next_packet_ts = 0; } Ok(()) } } /// Reads a MPEG frame and returns the header and buffer. fn read_mpeg_frame(reader: &mut MediaSourceStream) -> Result<(FrameHeader, Vec)> { let (header, header_word) = loop { // Sync to the next frame header. let sync = header::sync_frame(reader)?; // Parse the frame header fully. if let Ok(header) = header::parse_frame_header(sync) { break (header, sync); } warn!("invalid mpeg audio header"); }; // Allocate frame buffer. let mut packet = vec![0u8; MPEG_HEADER_LEN + header.frame_size]; packet[0..MPEG_HEADER_LEN].copy_from_slice(&header_word.to_be_bytes()); // Read the frame body. reader.read_buf_exact(&mut packet[MPEG_HEADER_LEN..])?; // Return the parsed header and packet body. Ok((header, packet)) } /// Reads a MPEG frame and checks if the next frame begins after the packet. fn read_mpeg_frame_strict(reader: &mut MediaSourceStream) -> Result<(FrameHeader, Vec)> { loop { // Read the next MPEG frame. let (header, packet) = read_mpeg_frame(reader)?; // Get the position before trying to read the next header. let pos = reader.pos(); // Read a sync word from the stream. If this read fails then the file may have ended and // this check cannot be performed. if let Ok(sync) = header::read_frame_header_word_no_sync(reader) { // If the stream is not synced to the next frame's sync word, or the next frame header // is not parseable or similar to the current frame header, then reject the current // packet since the stream likely synced to random data. if !header::is_frame_header_word_synced(sync) || !is_frame_header_similar(&header, sync) { warn!("skipping junk at {} bytes", pos - packet.len() as u64); // Seek back to the second byte of the rejected packet to prevent syncing to the // same spot again. reader.seek_buffered_rev(packet.len() + MPEG_HEADER_LEN - 1); continue; } } // Jump back to the position before the next header was read. reader.seek_buffered(pos); break Ok((header, packet)); } } /// Check if a sync word parses to a frame header that is similar to the one provided. fn is_frame_header_similar(header: &FrameHeader, sync: u32) -> bool { if let Ok(candidate) = header::parse_frame_header(sync) { if header.version == candidate.version && header.layer == candidate.layer && header.sample_rate == candidate.sample_rate && header.n_channels() == candidate.n_channels() { return true; } } false } #[derive(Default)] struct FramePos { ts: u64, pos: u64, } /// Reads the main_data_begin field from the side information of a MPEG audio frame. fn read_main_data_begin(reader: &mut B, header: &FrameHeader) -> Result { // After the head the optional CRC is present. if header.has_crc { let _crc = reader.read_be_u16()?; } // For MPEG version 1 the first 9 bits is main_data_begin. let main_data_begin = if header.is_mpeg1() { reader.read_be_u16()? >> 7 } // For MPEG version 2 the first 8 bits is main_data_begin. else { u16::from(reader.read_u8()?) }; Ok(main_data_begin) } /// Estimates the total number of MPEG frames in the media source stream. fn estimate_num_mpeg_frames(reader: &mut MediaSourceStream) -> Option { const MAX_FRAMES: u32 = 16; const MAX_LEN: usize = 16 * 1024; // Macro to convert a Result to Option, and break a loop on exit. macro_rules! break_on_err { ($expr:expr) => { match $expr { Ok(a) => a, _ => break None, } }; } let start_pos = reader.pos(); let mut total_frame_len = 0; let mut total_frames = 0; let total_len = match reader.byte_len() { Some(len) => len - start_pos, _ => return None, }; let num_mpeg_frames = loop { // Read the frame header. let header_val = break_on_err!(reader.read_be_u32()); // Parse the frame header. let header = break_on_err!(header::parse_frame_header(header_val)); // Tabulate the size. total_frame_len += MPEG_HEADER_LEN + header.frame_size; total_frames += 1; // Ignore the frame body. break_on_err!(reader.ignore_bytes(header.frame_size as u64)); // Read up-to 16 frames, or 16kB, then calculate the average MPEG frame length, and from // that, the total number of MPEG frames. if total_frames > MAX_FRAMES || total_frame_len > MAX_LEN { let avg_mpeg_frame_len = total_frame_len as f64 / total_frames as f64; break Some((total_len as f64 / avg_mpeg_frame_len) as u64); } }; // Rewind back to the first frame seen upon entering this function. reader.seek_buffered_rev((reader.pos() - start_pos) as usize); num_mpeg_frames } const XING_TAG_ID: [u8; 4] = *b"Xing"; const INFO_TAG_ID: [u8; 4] = *b"Info"; /// The LAME tag is an extension to the Xing/Info tag. #[allow(dead_code)] struct LameTag { encoder: String, replaygain_peak: Option, replaygain_radio: Option, replaygain_audiophile: Option, enc_delay: u32, enc_padding: u32, } /// The Xing/Info time additional information for regarding a MP3 file. #[allow(dead_code)] struct XingInfoTag { num_frames: Option, num_bytes: Option, toc: Option<[u8; 100]>, quality: Option, is_cbr: bool, lame: Option, } /// Try to read a Xing/Info tag from the provided MPEG frame. fn try_read_info_tag(buf: &[u8], header: &FrameHeader) -> Option { // The Info header is a completely optional piece of information. Therefore, flatten an error // reading the tag into a None. try_read_info_tag_inner(buf, header).ok().flatten() } fn try_read_info_tag_inner(buf: &[u8], header: &FrameHeader) -> Result> { // Do a quick check that this is a Xing/Info tag. if !is_maybe_info_tag(buf, header) { return Ok(None); } // The position of the Xing/Info tag relative to the end of the header. This is equal to the // side information length for the frame. let offset = header.side_info_len(); // Start the CRC with the header and side information. let mut crc16 = Crc16AnsiLe::new(0); crc16.process_buf_bytes(&buf[..offset + MPEG_HEADER_LEN]); // Start reading the Xing/Info tag after the side information. let mut reader = MonitorStream::new(BufReader::new(&buf[offset + MPEG_HEADER_LEN..]), crc16); // Check for Xing/Info header. let id = reader.read_quad_bytes()?; if id != XING_TAG_ID && id != INFO_TAG_ID { return Ok(None); } // The "Info" id is used for CBR files. let is_cbr = id == INFO_TAG_ID; // Flags indicates what information is provided in this Xing/Info tag. let flags = reader.read_be_u32()?; let num_frames = if flags & 0x1 != 0 { Some(reader.read_be_u32()?) } else { None }; let num_bytes = if flags & 0x2 != 0 { Some(reader.read_be_u32()?) } else { None }; let toc = if flags & 0x4 != 0 { let mut toc = [0; 100]; reader.read_buf_exact(&mut toc)?; Some(toc) } else { None }; let quality = if flags & 0x8 != 0 { Some(reader.read_be_u32()?) } else { None }; /// The full LAME extension size. const LAME_EXT_LEN: u64 = 36; /// The minimal LAME extension size up-to the encode delay & padding fields. const MIN_LAME_EXT_LEN: u64 = 24; // The LAME extension may not always be present, or complete. The important fields in the // extension are within the first 24 bytes. Therefore, try to read those if they're available. let lame = if reader.inner().bytes_available() >= MIN_LAME_EXT_LEN { // Encoder string. let mut encoder = [0; 9]; reader.read_buf_exact(&mut encoder)?; // Revision. let _revision = reader.read_u8()?; // Lowpass filter value. let _lowpass = reader.read_u8()?; // Replay gain peak in 9.23 (bit) fixed-point format. let replaygain_peak = match reader.read_be_u32()? { 0 => None, peak => Some(32767.0 * (peak as f32 / 2.0f32.powi(23))), }; // Radio replay gain. let replaygain_radio = parse_lame_tag_replaygain(reader.read_be_u16()?, 1); // Audiophile replay gain. let replaygain_audiophile = parse_lame_tag_replaygain(reader.read_be_u16()?, 2); // Encoding flags & ATH type. let _encoding_flags = reader.read_u8()?; // Arbitrary bitrate. let _abr = reader.read_u8()?; let (enc_delay, enc_padding) = { let trim = reader.read_be_u24()?; if encoder[..4] == *b"LAME" || encoder[..4] == *b"Lavf" || encoder[..4] == *b"Lavc" { let delay = 528 + 1 + (trim >> 12); let padding = trim & ((1 << 12) - 1); (delay, padding.saturating_sub(528 + 1)) } else { (0, 0) } }; // If possible, attempt to read the extra fields of the extension if they weren't // truncated. let crc = if reader.inner().bytes_available() >= LAME_EXT_LEN - MIN_LAME_EXT_LEN { // Flags. let _misc = reader.read_u8()?; // MP3 gain. let _mp3_gain = reader.read_u8()?; // Preset and surround info. let _surround_info = reader.read_be_u16()?; // Music length. let _music_len = reader.read_be_u32()?; // Music (audio) CRC. let _music_crc = reader.read_be_u16()?; // The tag CRC. LAME always includes this CRC regardless of the protection bit, but // other encoders may only do so if the protection bit is set. if header.has_crc || encoder[..4] == *b"LAME" { // Read the CRC using the inner reader to not change the computed CRC. Some(reader.inner_mut().read_be_u16()?) } else { // No CRC is present. None } } else { // The tag is truncated. No CRC will be present. info!("xing tag lame extension is truncated"); None }; // If there is no CRC, then assume the tag is correct. Otherwise, use the CRC. let is_tag_ok = crc.map_or(true, |crc| crc == reader.monitor().crc()); if is_tag_ok { // The CRC matched or is not present. Some(LameTag { encoder: String::from_utf8_lossy(&encoder).into(), replaygain_peak, replaygain_radio, replaygain_audiophile, enc_delay, enc_padding, }) } else { // The CRC did not match, this is probably not a LAME tag. warn!("xing tag lame extension crc mismatch"); None } } else { // Frame not large enough for a LAME tag. info!("xing tag too small for lame extension"); None }; Ok(Some(XingInfoTag { num_frames, num_bytes, toc, quality, is_cbr, lame })) } fn parse_lame_tag_replaygain(value: u16, expected_name: u8) -> Option { // The 3 most-significant bits are the name code. let name = ((value & 0xe000) >> 13) as u8; if name == expected_name { let gain = (value & 0x01ff) as f32 / 10.0; Some(if value & 0x200 != 0 { -gain } else { gain }) } else { None } } /// Perform a fast check to see if the packet contains a Xing/Info tag. If this returns true, the /// packet should be parsed fully to ensure it is in fact a tag. fn is_maybe_info_tag(buf: &[u8], header: &FrameHeader) -> bool { const MIN_XING_TAG_LEN: usize = 8; // Only supported with layer 3 packets. if header.layer != MpegLayer::Layer3 { return false; } // The position of the Xing/Info tag relative to the start of the packet. This is equal to the // side information length for the frame. let offset = header.side_info_len() + MPEG_HEADER_LEN; // The packet must be big enough to contain a tag. if buf.len() < offset + MIN_XING_TAG_LEN { return false; } // The tag ID must be present and correct. let id = &buf[offset..offset + 4]; if id != XING_TAG_ID && id != INFO_TAG_ID { return false; } // The side information should be zeroed. !buf[MPEG_HEADER_LEN..offset].iter().any(|&b| b != 0) } const VBRI_TAG_ID: [u8; 4] = *b"VBRI"; /// The contents of a VBRI tag. #[allow(dead_code)] struct VbriTag { num_bytes: u32, num_mpeg_frames: u32, } /// Try to read a VBRI tag from the provided MPEG frame. fn try_read_vbri_tag(buf: &[u8], header: &FrameHeader) -> Option { // The VBRI header is a completely optional piece of information. Therefore, flatten an error // reading the tag into a None. try_read_vbri_tag_inner(buf, header).ok().flatten() } fn try_read_vbri_tag_inner(buf: &[u8], header: &FrameHeader) -> Result> { // Do a quick check that this is a VBRI tag. if !is_maybe_vbri_tag(buf, header) { return Ok(None); } let mut reader = BufReader::new(buf); // The VBRI tag is always 32 bytes after the header. reader.ignore_bytes(MPEG_HEADER_LEN as u64 + 32)?; // Check for the VBRI signature. let id = reader.read_quad_bytes()?; if id != VBRI_TAG_ID { return Ok(None); } // The version is always 1. let version = reader.read_be_u16()?; if version != 1 { return Ok(None); } // Delay is a 2-byte big-endiann floating point value? let _delay = reader.read_be_u16()?; let _quality = reader.read_be_u16()?; let num_bytes = reader.read_be_u32()?; let num_mpeg_frames = reader.read_be_u32()?; Ok(Some(VbriTag { num_bytes, num_mpeg_frames })) } /// Perform a fast check to see if the packet contains a VBRI tag. If this returns true, the /// packet should be parsed fully to ensure it is in fact a tag. fn is_maybe_vbri_tag(buf: &[u8], header: &FrameHeader) -> bool { const MIN_VBRI_TAG_LEN: usize = 26; const VBRI_TAG_OFFSET: usize = 36; // Only supported with layer 3 packets. if header.layer != MpegLayer::Layer3 { return false; } // The packet must be big enough to contain a tag. if buf.len() < VBRI_TAG_OFFSET + MIN_VBRI_TAG_LEN { return false; } // The tag ID must be present and correct. let id = &buf[VBRI_TAG_OFFSET..VBRI_TAG_OFFSET + 4]; if id != VBRI_TAG_ID { return false; } // The bytes preceeding the VBRI tag (mostly the side information) should be all 0. !buf[MPEG_HEADER_LEN..VBRI_TAG_OFFSET].iter().any(|&b| b != 0) } symphonia-bundle-mp3-0.5.2/src/header.rs000064400000000000000000000223111046102023000161670ustar 00000000000000// Symphonia // Copyright (c) 2019-2022 The Project Symphonia Developers. // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. use symphonia_core::errors::{decode_error, unsupported_error, Result}; use symphonia_core::io::ReadBytes; use crate::common::*; /// The length in bytes of a MPEG frame header word. pub const MPEG_HEADER_LEN: usize = 4; /// The maximum length in bytes of a MPEG audio frame including the header. pub const MAX_MPEG_FRAME_SIZE: u64 = 2881; /// Bit-rate lookup table for MPEG version 1 layer 1. const BIT_RATES_MPEG1_L1: [u32; 15] = [ 0, 32_000, 64_000, 96_000, 128_000, 160_000, 192_000, 224_000, 256_000, 288_000, 320_000, 352_000, 384_000, 416_000, 448_000, ]; /// Bit-rate lookup table for MPEG version 1 layer 2. const BIT_RATES_MPEG1_L2: [u32; 15] = [ 0, 32_000, 48_000, 56_000, 64_000, 80_000, 96_000, 112_000, 128_000, 160_000, 192_000, 224_000, 256_000, 320_000, 384_000, ]; /// Bit-rate lookup table for MPEG version 1 layer 3. const BIT_RATES_MPEG1_L3: [u32; 15] = [ 0, 32_000, 40_000, 48_000, 56_000, 64_000, 80_000, 96_000, 112_000, 128_000, 160_000, 192_000, 224_000, 256_000, 320_000, ]; /// Bit-rate lookup table for MPEG version 2 & 2.5 audio layer 1. const BIT_RATES_MPEG2_L1: [u32; 15] = [ 0, 32_000, 48_000, 56_000, 64_000, 80_000, 96_000, 112_000, 128_000, 144_000, 160_000, 176_000, 192_000, 224_000, 256_000, ]; /// Bit-rate lookup table for MPEG version 2 & 2.5 audio layers 2 & 3. const BIT_RATES_MPEG2_L23: [u32; 15] = [ 0, 8_000, 16_000, 24_000, 32_000, 40_000, 48_000, 56_000, 64_000, 80_000, 96_000, 112_000, 128_000, 144_000, 160_000, ]; /// Quickly check if a header sync word may be valid. #[inline] pub fn check_header(header: u32) -> bool { // Version (0x1 is not allowed). if (header >> 19) & 0x3 == 0x1 { return false; } // Layer (0x0 is not allowed). if (header >> 17) & 0x3 == 0x0 { return false; } // Bitrate (0xf is not allowed). if (header >> 12) & 0xf == 0xf { return false; } // Sample rate (0x3 is not allowed). if (header >> 10) & 0x3 == 0x3 { return false; } // Emphasis (0x2 is not allowed) if header & 0x3 == 0x2 { return false; } true } /// Returns true if the provided frame header word is synced. #[inline(always)] pub fn is_frame_header_word_synced(sync: u32) -> bool { (sync & 0xffe0_0000) == 0xffe0_0000 } /// Synchronize the provided reader to the end of the frame header, and return the frame header as /// as `u32`. pub fn sync_frame(reader: &mut B) -> Result { let mut sync = 0u32; loop { // Synchronize stream to the next frame using the sync word. The MPEG audio frame header // always starts at a byte boundary with 0xffe (11 consecutive 1 bits.) if supporting up to // MPEG version 2.5. while !is_frame_header_word_synced(sync) { sync = (sync << 8) | u32::from(reader.read_u8()?); } // Random data can look like a sync word. Do a quick check to increase confidence that // this is may be the start of a frame. if check_header(sync) { break; } sync = (sync << 8) | u32::from(reader.read_u8()?); } Ok(sync) } pub fn parse_frame_header(header: u32) -> Result { // The MPEG audio header is structured as follows: // // 0b1111_1111 0b111v_vlly 0brrrr_hhpx 0bmmmm_coee // where: // vv = version, ll = layer , y = crc // rrrr = bitrate, hh = sample rate, p = padding , x = private bit // mmmm = mode , c = copyright , o = original, ee = emphasis let version = match (header & 0x18_0000) >> 19 { 0b00 => MpegVersion::Mpeg2p5, 0b10 => MpegVersion::Mpeg2, 0b11 => MpegVersion::Mpeg1, _ => return decode_error("mpa: invalid MPEG version"), }; let layer = match (header & 0x6_0000) >> 17 { 0b01 => MpegLayer::Layer3, 0b10 => MpegLayer::Layer2, 0b11 => MpegLayer::Layer1, _ => return decode_error("mpa: invalid MPEG layer"), }; let bitrate = match ((header & 0xf000) >> 12, version, layer) { // "Free" bit-rate. Note, this is NOT variable bit-rate and is not a mandatory feature of // MP3 decoders. (0b0000, _, _) => return unsupported_error("mpa: free bit-rate is not supported"), // Invalid bit-rate. (0b1111, _, _) => return decode_error("mpa: invalid bit-rate"), // MPEG 1 bit-rates. (i, MpegVersion::Mpeg1, MpegLayer::Layer1) => BIT_RATES_MPEG1_L1[i as usize], (i, MpegVersion::Mpeg1, MpegLayer::Layer2) => BIT_RATES_MPEG1_L2[i as usize], (i, MpegVersion::Mpeg1, MpegLayer::Layer3) => BIT_RATES_MPEG1_L3[i as usize], // MPEG 2 bit-rates. (i, _, MpegLayer::Layer1) => BIT_RATES_MPEG2_L1[i as usize], (i, _, _) => BIT_RATES_MPEG2_L23[i as usize], }; let (sample_rate, sample_rate_idx) = match ((header & 0xc00) >> 10, version) { (0b00, MpegVersion::Mpeg1) => (44_100, 0), (0b01, MpegVersion::Mpeg1) => (48_000, 1), (0b10, MpegVersion::Mpeg1) => (32_000, 2), (0b00, MpegVersion::Mpeg2) => (22_050, 3), (0b01, MpegVersion::Mpeg2) => (24_000, 4), (0b10, MpegVersion::Mpeg2) => (16_000, 5), (0b00, MpegVersion::Mpeg2p5) => (11_025, 6), (0b01, MpegVersion::Mpeg2p5) => (12_000, 7), (0b10, MpegVersion::Mpeg2p5) => (8_000, 8), _ => return decode_error("mpa: invalid sample rate"), }; let channel_mode = match ((header & 0xc0) >> 6, layer) { // Stereo, for layers 1, 2, and 3. (0b00, _) => ChannelMode::Stereo, // Dual mono, for layers 1, 2, and 3. (0b10, _) => ChannelMode::DualMono, // Mono, for layers 1, 2, and 3. (0b11, _) => ChannelMode::Mono, // Joint stereo mode for layer 3 supports a combination of Mid-Side and Intensity Stereo // depending on the mode extension bits. (0b01, MpegLayer::Layer3) => ChannelMode::JointStereo(Mode::Layer3 { mid_side: header & 0x20 != 0x0, intensity: header & 0x10 != 0x0, }), // Joint stereo mode for layers 1 and 2 only supports Intensity Stereo. The mode extension // bits indicate for which sub-bands intensity stereo coding is applied. (0b01, _) => { ChannelMode::JointStereo(Mode::Intensity { bound: (1 + ((header & 0x30) >> 4)) << 2 }) } _ => unreachable!(), }; // Some layer 2 channel and bit-rate combinations are not allowed. Check that the frame does not // use them. if layer == MpegLayer::Layer2 { if channel_mode == ChannelMode::Mono { if bitrate == 224_000 || bitrate == 256_000 || bitrate == 320_000 || bitrate == 384_000 { return decode_error("mpa: invalid Layer 2 bitrate for mono channel mode"); } } else if bitrate == 32_000 || bitrate == 48_000 || bitrate == 56_000 || bitrate == 80_000 { return decode_error("mpa: invalid Layer 2 bitrate for non-mono channel mode"); } } let emphasis = match header & 0x3 { 0b00 => Emphasis::None, 0b01 => Emphasis::Fifty15, 0b11 => Emphasis::CcitJ17, _ => return decode_error("mpa: invalid emphasis"), }; let is_copyrighted = header & 0x8 != 0x0; let is_original = header & 0x4 != 0x0; let has_padding = header & 0x200 != 0; let has_crc = header & 0x1_0000 == 0; // Constants provided for size calculation in section ISO-11172 section 2.4.3.1. let factor = match layer { MpegLayer::Layer1 => 12, MpegLayer::Layer2 => 144, MpegLayer::Layer3 if version == MpegVersion::Mpeg1 => 144, MpegLayer::Layer3 => 72, }; // The header specifies the total frame size in "slots". For layers 2 & 3 a slot is 1 byte, // however for layer 1 a slot is 4 bytes. let slot_size = match layer { MpegLayer::Layer1 => 4, _ => 1, }; // Calculate the total frame size in number of slots. let frame_size_slots = (factor * bitrate / sample_rate) as usize + usize::from(has_padding); // Calculate the frame size in bytes, excluding the header. let frame_size = (frame_size_slots * slot_size) - 4; Ok(FrameHeader { version, layer, bitrate, sample_rate, sample_rate_idx, channel_mode, emphasis, is_copyrighted, is_original, has_padding, has_crc, frame_size, }) } /// Synchronize the stream to the start of the next MPEG audio frame header, then read and return /// the frame header or an error. #[inline] #[allow(dead_code)] pub fn read_frame_header(reader: &mut B) -> Result { // Synchronize and parse the frame header. parse_frame_header(sync_frame(reader)?) } /// Read a MPEG audio frame header word from the current location in the stream without any frame /// synchronization. #[inline] pub fn read_frame_header_word_no_sync(reader: &mut B) -> Result { Ok(reader.read_be_u32()?) } symphonia-bundle-mp3-0.5.2/src/layer1/mod.rs000064400000000000000000000143711046102023000167220ustar 00000000000000// Symphonia // Copyright (c) 2019-2022 The Project Symphonia Developers. // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. use symphonia_core::audio::{AudioBuffer, Signal}; use symphonia_core::errors::{decode_error, Result}; use symphonia_core::io::{BitReaderLtr, BufReader, ReadBitsLtr, ReadBytes}; use symphonia_core::util::bits::sign_extend_leq32_to_i32; use crate::common::*; use crate::layer12::LAYER12_SCALEFACTORS; use crate::synthesis; use lazy_static::lazy_static; lazy_static! { static ref FACTOR: [f32; 16] = { let mut factor = [0f32; 16]; for (i, factor) in factor.iter_mut().enumerate().skip(2) { // As per ISO/IEC 11172-3, given the nb-bit signed raw sample, val, dequantization is // defined as follows. // // fractional = val / 2^(nb - 1) // dequantized = (2^nb) / (2^nb - 1) * (fractional * 2^(-nb + 1)) // // After combining, expanding, and simplifying the above equations, the complete // calculation can be expressed as below. // // [(2^nb) / ((2^nb) - 1)] * 2^(-nb + 1) * (val + 1) // ------------------------------------- // factor // // Therefore, dequantization can be reduced to a single multiplication and addition. // This lookup table generator computes factor for nb-bits between 2..15, inclusive. let a = 1 << i; let b = 1 << (i - 1); *factor = (a as f32 / (a - 1) as f32) * (b as f32).recip(); } factor }; } /// Dequantize a sample, `raw`, of length `bits` bits. #[inline(always)] fn dequantize(bits: u32, factor: f32, raw: u32) -> f32 { // Invert the most significant bit. let inv = raw ^ 1 << (bits - 1); // Sign extend the sample. let a = sign_extend_leq32_to_i32(inv, bits); // Dequantize the sample. factor * (a + 1) as f32 } pub struct Layer1 { pub synthesis: [synthesis::SynthesisState; 2], } impl Layer1 { pub fn new() -> Self { Self { synthesis: Default::default() } } } impl Layer for Layer1 { fn decode( &mut self, reader: &mut BufReader<'_>, header: &FrameHeader, out: &mut AudioBuffer, ) -> Result<()> { // Ignore the CRC. let _crc = if header.has_crc { Some(reader.read_be_u16()?) } else { None }; let mut bs = BitReaderLtr::new(reader.read_buf_bytes_available_ref()); let mut alloc = [[0; 32]; 2]; let mut scalefacs = [[0.0; 32]; 2]; let num_channels = header.n_channels(); let bound = match header.channel_mode { ChannelMode::JointStereo(Mode::Intensity { bound }) => bound as usize, ChannelMode::JointStereo(Mode::Layer3 { .. }) => { // This mode extension is exclusively used for layer 3, it is a fundamental error // in the decoder logic if layer 1 or 2 stereo encodings are being decoded with // this function. panic!("invalid mode extension for layer 1 stereo decoding") } _ => 32, }; // Read bit allocations for each non-intensity coded sub-bands. for sb in 0..bound { for chan in &mut alloc { let bits = bs.read_bits_leq32(4)? as u8; if bits > 0xe { return decode_error("mp1: invalid bit allocation"); } chan[sb] = if bits != 0 { bits + 1 } else { 0 }; } } // Read bit allocations for the intensity coded sub-bands. for sb in bound..32 { let bits = bs.read_bits_leq32(4)? as u8; if bits > 0xe { return decode_error("mp1: invalid bit allocation"); } let ba = if bits != 0 { bits + 1 } else { 0 }; alloc[0][sb] = ba; alloc[1][sb] = ba; } // Read scalefactors for each sub-band. for sb in 0..32 { for ch in 0..num_channels { if alloc[ch][sb] != 0 { let index = bs.read_bits_leq32(6)? as usize; scalefacs[ch][sb] = LAYER12_SCALEFACTORS[index]; } } } let factor = &FACTOR; // Decode samples. let mut samples = [[0f32; 384]; 2]; for s in 0..12 { // Non-intensity coded sub-bands. for sb in 0..bound { for ch in 0..num_channels { let bits = u32::from(alloc[ch][sb]); if bits != 0 { // Read the raw sample value from the bistream. let raw = bs.read_bits_leq32(bits)?; // Dequantize the raw sample. let sample = dequantize(bits, factor[bits as usize], raw); // Unscale the sample. samples[ch][12 * sb + s] = scalefacs[ch][sb] * sample; } } } // Intensity coded sub-bands. for sb in bound..32 { let bits = u32::from(alloc[0][sb]); if bits != 0 { // Read the raw sample value from the bistream. let raw = bs.read_bits_leq32(bits)?; // Dequantize the raw sample. let sample = dequantize(bits, factor[bits as usize], raw); // Unscale the sample and copy it into both channels. for ch in 0..num_channels { samples[ch][12 * sb + s] = scalefacs[ch][sb] * sample; } } } } // Each packet will yield 384 audio frames. After reserving frames, all steps must be // infalliable. out.render_reserved(Some(384)); for (ch, samples) in samples.iter().enumerate().take(num_channels) { // Perform polyphase synthesis and generate PCM samples. synthesis::synthesis(&mut self.synthesis[ch], 12, samples, out.chan_mut(ch)); } Ok(()) } } symphonia-bundle-mp3-0.5.2/src/layer12.rs000064400000000000000000000037331046102023000162250ustar 00000000000000// Symphonia // Copyright (c) 2019-2022 The Project Symphonia Developers. // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. /// Layer 1 and 2 shared scale factors. Derived from ISO/ISO 11172-3 Table 3-B.1. pub const LAYER12_SCALEFACTORS: [f32; 64] = [ 2.00000000000000, 1.58740105196820, 1.25992104989487, 1.00000000000000, 0.79370052598410, 0.62996052494744, 0.50000000000000, 0.39685026299205, 0.31498026247372, 0.25000000000000, 0.19842513149602, 0.15749013123686, 0.12500000000000, 0.09921256574801, 0.07874506561843, 0.06250000000000, 0.04960628287401, 0.03937253280921, 0.03125000000000, 0.02480314143700, 0.01968626640461, 0.01562500000000, 0.01240157071850, 0.00984313320230, 0.00781250000000, 0.00620078535925, 0.00492156660115, 0.00390625000000, 0.00310039267963, 0.00246078330058, 0.00195312500000, 0.00155019633981, 0.00123039165029, 0.00097656250000, 0.00077509816991, 0.00061519582514, 0.00048828125000, 0.00038754908495, 0.00030759791257, 0.00024414062500, 0.00019377454248, 0.00015379895629, 0.00012207031250, 0.00009688727124, 0.00007689947814, 0.00006103515625, 0.00004844363562, 0.00003844973907, 0.00003051757813, 0.00002422181781, 0.00001922486954, 0.00001525878906, 0.00001211090890, 0.00000961243477, 0.00000762939453, 0.00000605545445, 0.00000480621738, 0.00000381469727, 0.00000302772723, 0.00000240310869, 0.00000190734863, 0.00000151386361, 0.00000120155435, // This value is not in the table provided by ISO/IEC 11172-3. However, some files do use 63 as // a scalefactor index. To increase compatibility, a dummy scalefactor has been added. 0.00000000000000, ]; symphonia-bundle-mp3-0.5.2/src/layer2/mod.rs000064400000000000000000000344761046102023000167330ustar 00000000000000// Symphonia // Copyright (c) 2019-2022 The Project Symphonia Developers. // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. use symphonia_core::audio::{AudioBuffer, Signal}; use symphonia_core::errors::Result; use symphonia_core::io::{BitReaderLtr, BufReader, ReadBitsLtr, ReadBytes}; use symphonia_core::util::bits::sign_extend_leq32_to_i32; use crate::common::{ChannelMode, FrameHeader, Layer, Mode}; use crate::layer12::LAYER12_SCALEFACTORS; use crate::synthesis; struct QuantClass { /// C constant. c: f32, /// D constant. d: f32, /// Is grouping used? grouping: bool, /// Bits per raw sample (if grouping is false) or codeword (if grouping is true). bits: u8, /// Number of levels in a sample. nlevels: u16, } struct SbQuantInfo { /// Bit allocation for the sub-band. nbal: u8, /// Indicies into quantization class table. Valid for classes 0..2^nbal. classes: [u8; 16], } struct SbInfo { /// The maximum number of sub-bands. sblimit: usize, /// An index into the sub-band information table for each sub-band. Valid for sub-bands between /// 0..sblimit. bands: [u8; 32], } /// Quantization classes. Derived from ISO/IEC 11172-3 Table 3-B.4. const QUANT_CLASS: [QuantClass; 17] = [ QuantClass { c: 1.33333333333, d: 0.50000000000, grouping: true, bits: 5, nlevels: 3 }, QuantClass { c: 1.60000000000, d: 0.50000000000, grouping: true, bits: 7, nlevels: 5 }, QuantClass { c: 1.14285714286, d: 0.25000000000, grouping: false, bits: 3, nlevels: 7 }, QuantClass { c: 1.77777777777, d: 0.50000000000, grouping: true, bits: 10, nlevels: 9 }, QuantClass { c: 1.06666666666, d: 0.12500000000, grouping: false, bits: 4, nlevels: 15 }, QuantClass { c: 1.03225806452, d: 0.06250000000, grouping: false, bits: 5, nlevels: 31 }, QuantClass { c: 1.01587301587, d: 0.03125000000, grouping: false, bits: 6, nlevels: 63 }, QuantClass { c: 1.00787401575, d: 0.01562500000, grouping: false, bits: 7, nlevels: 127 }, QuantClass { c: 1.00392156863, d: 0.00781250000, grouping: false, bits: 8, nlevels: 255 }, QuantClass { c: 1.00195694716, d: 0.00390625000, grouping: false, bits: 9, nlevels: 511 }, QuantClass { c: 1.00097751711, d: 0.00195312500, grouping: false, bits: 10, nlevels: 1023 }, QuantClass { c: 1.00048851979, d: 0.00097656250, grouping: false, bits: 11, nlevels: 2047 }, QuantClass { c: 1.00024420024, d: 0.00048828125, grouping: false, bits: 12, nlevels: 4095 }, QuantClass { c: 1.00012208522, d: 0.00024414063, grouping: false, bits: 13, nlevels: 8191 }, QuantClass { c: 1.00006103888, d: 0.00012207031, grouping: false, bits: 14, nlevels: 16383 }, QuantClass { c: 1.00003051851, d: 0.00006103516, grouping: false, bits: 15, nlevels: 32767 }, QuantClass { c: 1.00001525902, d: 0.00003051758, grouping: false, bits: 16, nlevels: 65535 }, ]; /// Sub-band quantization class information. Derived from ISO/IEC 11172-3 Tables 3-B.2a-d. const SB_QUANT_INFO: [SbQuantInfo; 8] = [ SbQuantInfo { nbal: 2, classes: [0, 0, 1, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] }, SbQuantInfo { nbal: 2, classes: [0, 0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] }, SbQuantInfo { nbal: 3, classes: [0, 0, 1, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0] }, SbQuantInfo { nbal: 3, classes: [0, 0, 1, 2, 3, 4, 5, 16, 0, 0, 0, 0, 0, 0, 0, 0] }, SbQuantInfo { nbal: 4, classes: [0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14] }, SbQuantInfo { nbal: 4, classes: [0, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] }, SbQuantInfo { nbal: 4, classes: [0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16] }, SbQuantInfo { nbal: 4, classes: [0, 0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] }, ]; /// Sub-band information table. const SB_INFO: [SbInfo; 5] = [ // Derived from ISO/IEC 11172-3 Table 3-B.2a. SbInfo { sblimit: 27, bands: [ 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }, // Derived from ISO/IEC 11172-3 Table 3-B.2b. SbInfo { sblimit: 30, bands: [ 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }, // Derived from ISO/IEC 11172-3 Table 3-B.2c. SbInfo { sblimit: 8, bands: [ 5, 5, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }, // Derived from ISO/IEC 11172-3 Table 3-B.2d. SbInfo { sblimit: 12, bands: [ 5, 5, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }, // Derived from ISO/IEC 13818-3 Table 3-B.1. SbInfo { sblimit: 30, bands: [ 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, ], }, ]; /// Get quantization class for a specific class index. #[inline(always)] fn find_quant_class(sb_quant_info: &SbQuantInfo, class: u8) -> &'static QuantClass { &QUANT_CLASS[usize::from(sb_quant_info.classes[usize::from(class)])] } /// Get quantization information for a specific sub-band. #[inline(always)] fn find_sb_quant_info(sb_info: &SbInfo, sb: usize) -> &'static SbQuantInfo { &SB_QUANT_INFO[usize::from(sb_info.bands[sb])] } /// Get sub-band information for a frame with a given header. fn find_sb_info(header: &FrameHeader) -> &'static SbInfo { let idx = if header.is_mpeg1() { // MPEG1 switches quantization tables based on bitrate per channel and sample rate. let num_channels = if header.channel_mode == ChannelMode::Mono { 1 } else { 2 }; let bitrate_per_channel = header.bitrate / num_channels; if bitrate_per_channel <= 48_000 { // Table 3-B.2c and 3-B.2d are only used for bitrates <= 48 kbit/s. if header.sample_rate == 32_000 { 3 } else { 2 } } else if bitrate_per_channel <= 80_000 { // Table 3-B.2a is always used for 48 kbit/s < bitrates <= 80 kbits/s. 0 } else { // Table 3-B.2a and 3-B.2b as always used for bitrates > 80 kbit/s. // TODO: Free format also used this case, but we don't support it. usize::from(header.sample_rate != 48_000) } } else { // MPEG2 & MPEG2.5 use the same table regardless of bitrate and sample rate. 4 }; &SB_INFO[idx] } /// Dequantize a sample, `raw`, of length `bits` bits. #[inline] fn dequantize(bs: &mut BitReaderLtr<'_>, class: &QuantClass) -> Result<[f32; 3]> { let mut raw = [0; 3]; let bits = if class.grouping { // Read a packed (grouped) codeword from the bitstream, and unpack the codeword into 3 // raw samples. let mut c = bs.read_bits_leq32(u32::from(class.bits))?; let nlevels = u32::from(class.nlevels); for item in &mut raw { *item = c % nlevels; c /= nlevels; } // Each raw sample is in the range 0..nlevels. Therefore, the bit width of an individual // raw sample is the minimum number of bits it takes to represent nlevels. nlevels.next_power_of_two().trailing_zeros() } else { // Read individial raw samples from the bitstream. let bits = u32::from(class.bits); for item in &mut raw { *item = bs.read_bits_leq32(bits)?; } bits }; // The divisor for samples of `bits` width. Used to convert the raw integer sample into a // floating point sample. let divisor = (1 << (bits - 1)) as f32; let mut samples = [0.0; 3]; for i in 0..3 { // Invert the most significant bit. let inv = raw[i] ^ 1 << (bits - 1); // Sign extend the sample. let a = sign_extend_leq32_to_i32(inv, bits); // Convert the sample into a fraction. let s = a as f32 / divisor; // Dequantize the sample. samples[i] = class.c * (s + class.d); } Ok(samples) } pub struct Layer2 { pub synthesis: [synthesis::SynthesisState; 2], } impl Layer2 { pub fn new() -> Self { Self { synthesis: Default::default() } } } impl Layer for Layer2 { fn decode( &mut self, reader: &mut BufReader<'_>, header: &FrameHeader, out: &mut AudioBuffer, ) -> Result<()> { // Ignore the CRC. let _crc = if header.has_crc { Some(reader.read_be_u16()?) } else { None }; let mut bs = BitReaderLtr::new(reader.read_buf_bytes_available_ref()); let mut alloc = [[0; 32]; 2]; let mut scfsi = [[0; 32]; 2]; let mut scalefacs = [[[0; 32]; 3]; 2]; let num_channels = header.n_channels(); let sb_info = find_sb_info(header); let bound = match header.channel_mode { ChannelMode::JointStereo(Mode::Intensity { bound }) => bound as usize, ChannelMode::JointStereo(Mode::Layer3 { .. }) => { // This mode extension is exclusively used for layer 3, it is a fundamental error // in the decoder logic if layer 1 or 2 stereo encodings are being decoded with // this function. panic!("invalid mode extension for layer 2 stereo decoding") } _ => 32, } .min(sb_info.sblimit); // Read the class index (allocation in the standard) for each non-intensity coded sub-band. for sb in 0..bound { let nbal = find_sb_quant_info(sb_info, sb).nbal; for chan in &mut alloc[..num_channels] { chan[sb] = bs.read_bits_leq32(u32::from(nbal))? as u8; } } // Read the class index (allocation in the standard) for each intensity coded sub-band. for sb in bound..sb_info.sblimit { let nbal = find_sb_quant_info(sb_info, sb).nbal; let value = bs.read_bits_leq32(u32::from(nbal))? as u8; alloc[0][sb] = value; alloc[1][sb] = value; } // Read scale factor selection information. for sb in 0..sb_info.sblimit { for ch in 0..num_channels { if alloc[ch][sb] != 0 { scfsi[ch][sb] = bs.read_bits_leq32(2)? as u8; } } } // Read scale factors. for sb in 0..sb_info.sblimit { for ch in 0..num_channels { if alloc[ch][sb] != 0 { let mut indicies = [bs.read_bits_leq32(6)? as u8; 3]; match scfsi[ch][sb] { 0 => { indicies[1] = bs.read_bits_leq32(6)? as u8; indicies[2] = bs.read_bits_leq32(6)? as u8; } 1 => { indicies[2] = bs.read_bits_leq32(6)? as u8; } 2 => (), 3 => { indicies[1] = bs.read_bits_leq32(6)? as u8; indicies[2] = indicies[1]; } _ => unreachable!(), } scalefacs[ch][0][sb] = indicies[0]; scalefacs[ch][1][sb] = indicies[1]; scalefacs[ch][2][sb] = indicies[2]; } } } // Decode samples. let mut samples = [[0f32; 1152]; 2]; for gr in 0..12 { // Non-intensity coded sub-bands. for sb in 0..bound { let sb_quant_info = find_sb_quant_info(sb_info, sb); for ch in 0..num_channels { let class_idx = alloc[ch][sb]; if class_idx != 0 { let quant_class = find_quant_class(sb_quant_info, class_idx); // Samples within a sub-band are decoded in-order. Dequantize the next group // of three samples for the sub-band. let triplet = dequantize(&mut bs, quant_class)?; // A sub-band is divided into three partitions of 12 samples each. Each // partition has its own scalefactor. Therefore, the partition index can be // calculated by 3 * gr / 12, or simplified, gr / 4. let scalefac = LAYER12_SCALEFACTORS[usize::from(scalefacs[ch][gr / 4][sb])]; // Unpack and unscale the samples. samples[ch][36 * sb + 3 * gr + 0] = scalefac * triplet[0]; samples[ch][36 * sb + 3 * gr + 1] = scalefac * triplet[1]; samples[ch][36 * sb + 3 * gr + 2] = scalefac * triplet[2]; } } } // Intensity coded sub-bands. for sb in bound..sb_info.sblimit { // Same decode procedure as non-intensity coded sub-bands, but the same pre-scaled // sample value is used for both channels. let class_idx = alloc[0][sb]; if class_idx != 0 { let quant_class = find_quant_class(find_sb_quant_info(sb_info, sb), class_idx); let triplet = dequantize(&mut bs, quant_class)?; for ch in 0..num_channels { let scalefac = LAYER12_SCALEFACTORS[usize::from(scalefacs[ch][gr / 4][sb])]; samples[ch][36 * sb + 3 * gr + 0] = scalefac * triplet[0]; samples[ch][36 * sb + 3 * gr + 1] = scalefac * triplet[1]; samples[ch][36 * sb + 3 * gr + 2] = scalefac * triplet[2]; } } } } // Each packet will yield 1152 audio frames. After reserving frames, all steps must be // infalliable. out.render_reserved(Some(1152)); for (ch, samples) in samples.iter().enumerate().take(num_channels) { // Perform polyphase synthesis and generate PCM samples. synthesis::synthesis(&mut self.synthesis[ch], 36, samples, out.chan_mut(ch)); } Ok(()) } } symphonia-bundle-mp3-0.5.2/src/layer3/bitstream.rs000064400000000000000000000404231046102023000201340ustar 00000000000000// Symphonia // Copyright (c) 2019-2022 The Project Symphonia Developers. // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. use symphonia_core::errors::{decode_error, Result}; use symphonia_core::io::ReadBitsLtr; use crate::common::{ChannelMode, FrameHeader}; use super::{common::*, FrameData, Granule, GranuleChannel}; /// Pairs of bit lengths for MPEG version 1 scale factors. For MPEG version 1, there are two /// possible bit lengths for scale factors: slen1 and slen2. The first N of bands have scale factors /// of bit length slen1, while the remaining bands have length slen2. The value of the switch point, /// N, is determined by block type. /// /// This table is indexed by scalefac_compress. const SCALE_FACTOR_SLEN: [(u32, u32); 16] = [ (0, 0), (0, 1), (0, 2), (0, 3), (3, 0), (1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (3, 3), (4, 2), (4, 3), ]; /// For MPEG version 2, each scale factor band has a different scale factor. The length in bits of /// a scale factor (slen) can be one of 4 values. The values in this table indicate the number of /// scale factors that have length slen[0..4]. Slen[0..4] is calculated from scalefac_compress. /// /// This table is indexed by channel_mode, scalefac_compress, and block_type. const SCALE_FACTOR_MPEG2_NSFB: [[[usize; 4]; 3]; 6] = [ // Intensity stereo channel modes. [[7, 7, 7, 0], [12, 12, 12, 0], [6, 15, 12, 0]], [[6, 6, 6, 3], [12, 9, 9, 6], [6, 12, 9, 6]], [[8, 8, 5, 0], [15, 12, 9, 0], [6, 18, 9, 0]], // Other channel modes. [[6, 5, 5, 5], [9, 9, 9, 9], [6, 9, 9, 9]], [[6, 5, 7, 3], [9, 9, 12, 6], [6, 9, 12, 6]], [[11, 10, 0, 0], [18, 18, 0, 0], [15, 18, 0, 0]], ]; /// Reads the side_info for a single channel in a granule from a `BitStream`. fn read_granule_channel_side_info( bs: &mut B, channel: &mut GranuleChannel, header: &FrameHeader, ) -> Result<()> { channel.part2_3_length = bs.read_bits_leq32(12)? as u16; channel.big_values = bs.read_bits_leq32(9)? as u16; // The maximum number of samples in a granule is 576. One big_value decodes to 2 samples, // therefore there can be no more than 288 (576/2) big_values. if channel.big_values > 288 { return decode_error("mpa: granule big_values > 288"); } channel.global_gain = bs.read_bits_leq32(8)? as u8; channel.scalefac_compress = if header.is_mpeg1() { bs.read_bits_leq32(4) } else { bs.read_bits_leq32(9) }? as u16; let window_switching = bs.read_bool()?; if window_switching { let block_type_enc = bs.read_bits_leq32(2)?; let is_mixed = bs.read_bool()?; channel.block_type = match block_type_enc { // Only transitional Long blocks (Start, End) are allowed with window switching. 0b00 => return decode_error("mpa: invalid block_type"), 0b01 => BlockType::Start, 0b10 => BlockType::Short { is_mixed }, 0b11 => BlockType::End, _ => unreachable!(), }; // When window switching is used, there are only two regions, therefore there are only // two table selectors. for i in 0..2 { channel.table_select[i] = bs.read_bits_leq32(5)? as u8; } for i in 0..3 { channel.subblock_gain[i] = bs.read_bits_leq32(3)? as u8; } // When using window switching, the boundaries of region[0..3] are set implicitly according // to the MPEG version and block type. Below, the boundaries to set as per the applicable // standard. // // If MPEG version 2.5 specifically... if header.is_mpeg2p5() { // For MPEG2.5, the number of scale-factor bands in region0 depends on the block type. // The standard indicates these values as 1 less than the actual value, therefore 1 is // added here to both values. let region0_count = match channel.block_type { BlockType::Short { is_mixed: false } => 5 + 1, _ => 7 + 1, }; channel.region1_start = SFB_LONG_BANDS[header.sample_rate_idx][region0_count]; } // If MPEG version 1, OR the block type is Short... else if header.is_mpeg1() || block_type_enc == 0b10 { // For MPEG1 with transitional LONG blocks, the first 8 LONG scale-factor bands are used // for region0. These bands are always [4, 4, 4, 4, 4, 4, 6, 6, ...] regardless of // sample rate. These bands sum to 36 samples. // // For MPEG1 with SHORT blocks, the first 9 SHORT scale-factor bands are used for // region0. These band are always [4, 4, 4, 4, 4, 4, 4, 4, 4, ...] regardless of sample // rate. These bands also sum to 36 samples. // // Finally, for MPEG2 with SHORT blocks, the first 9 short scale-factor bands are used // for region0. These bands are also always [4, 4, 4, 4, 4, 4, 4, 4, 4, ...] regardless // of sample and thus sum to 36 samples. // // In all cases, the region0_count is 36. // // TODO: This is not accurate for MPEG2.5 at 8kHz. channel.region1_start = 36; } // If MPEG version 2 AND the block type is not Short... else { // For MPEG2 and transitional LONG blocks, the first 8 LONG scale-factor bands are used // for region0. These bands are always [6, 6, 6, 6, 6, 6, 8, 10, ...] regardless of // sample rate. These bands sum to 54. channel.region1_start = 54; } // The second region, region1, spans the remaining samples. Therefore the third region, // region2, isn't used. channel.region2_start = 576; } else { // If window switching is not used, the block type is always Long. channel.block_type = BlockType::Long; for i in 0..3 { channel.table_select[i] = bs.read_bits_leq32(5)? as u8; } // When window switching is not used, only LONG scale-factor bands are used for each region. // The number of bands in region0 and region1 are defined in side_info. The stored value is // 1 less than the actual value. let region0_count = bs.read_bits_leq32(4)? as usize + 1; let region0_1_count = bs.read_bits_leq32(3)? as usize + region0_count + 1; channel.region1_start = SFB_LONG_BANDS[header.sample_rate_idx][region0_count]; // The count in region0_1_count may exceed the last band (22) in the LONG bands table. // Protect against this. channel.region2_start = match region0_1_count { 0..=22 => SFB_LONG_BANDS[header.sample_rate_idx][region0_1_count], _ => 576, }; } // For MPEG2, preflag is determined implicitly when reading the scale factors. channel.preflag = if header.is_mpeg1() { bs.read_bool()? } else { false }; channel.scalefac_scale = bs.read_bool()?; channel.count1table_select = bs.read_bit()? as u8; Ok(()) } /// Reads the side_info for all channels in a granule from a `BitStream`. fn read_granule_side_info( bs: &mut B, granule: &mut Granule, header: &FrameHeader, ) -> Result<()> { // Read the side_info for each channel in the granule. for channel in &mut granule.channels[..header.channel_mode.count()] { read_granule_channel_side_info(bs, channel, header)?; } Ok(()) } /// Reads the side_info of a MPEG audio frame from a `BitStream` into `FrameData`. pub(super) fn read_side_info( bs: &mut B, header: &FrameHeader, frame_data: &mut FrameData, ) -> Result { // For MPEG version 1... if header.is_mpeg1() { // First 9 bits is main_data_begin. frame_data.main_data_begin = bs.read_bits_leq32(9)? as u16; // Next 3 (>1 channel) or 5 (1 channel) bits are private and should be ignored. match header.channel_mode { ChannelMode::Mono => bs.ignore_bits(5)?, _ => bs.ignore_bits(3)?, }; // Next four (or 8, if more than one channel) are the SCFSI bits. for scfsi in &mut frame_data.scfsi[..header.n_channels()] { for band in scfsi.iter_mut() { *band = bs.read_bool()?; } } } // For MPEG version 2... else { // First 8 bits is main_data_begin. frame_data.main_data_begin = bs.read_bits_leq32(8)? as u16; // Next 1 (1 channel) or 2 (>1 channel) bits are private and should be ignored. match header.channel_mode { ChannelMode::Mono => bs.ignore_bits(1)?, _ => bs.ignore_bits(2)?, } } // Read the side_info for each granule. for granule in frame_data.granules_mut(header.version) { read_granule_side_info(bs, granule, header)?; } Ok(header.side_info_len()) } /// Reads the scale factors for a single channel in a granule in a MPEG version 1 audio frame. pub(super) fn read_scale_factors_mpeg1( bs: &mut B, gr: usize, ch: usize, frame_data: &mut FrameData, ) -> Result { let mut bits_read = 0; let channel = &mut frame_data.granules[gr].channels[ch]; // For MPEG1, scalefac_compress is a 4-bit index into a scale factor bit length lookup table. let (slen1, slen2) = SCALE_FACTOR_SLEN[channel.scalefac_compress as usize]; // Short or Mixed windows... if let BlockType::Short { is_mixed } = channel.block_type { // If the block is mixed, there are three total scale factor partitions. The first is a long // scale factor partition for bands 0..8 (scalefacs[0..8] with each scale factor being slen1 // bits long. Following this is a short scale factor partition covering bands 8..11 with a // window of 3 (scalefacs[8..17]) and each scale factoring being slen1 bits long. // // If a block is not mixed, then there are a total of two scale factor partitions. The first // is a short scale factor partition for bands 0..6 with a window length of 3 // (scalefacs[0..18]) and each scale factor being slen1 bits long. let n_sfb = if is_mixed { 8 + 3 * 3 } else { 6 * 3 }; if slen1 > 0 { for sfb in 0..n_sfb { channel.scalefacs[sfb] = bs.read_bits_leq32(slen1)? as u8; } bits_read += n_sfb * slen1 as usize; } // The final scale factor partition is always a a short scale factor window. It covers bands // 11..17 (scalefacs[17..35]) if the block is mixed, or bands 6..12 (scalefacs[18..36]) if // not. Each band has a window of 3 with each scale factor being slen2 bits long. if slen2 > 0 { for sfb in n_sfb..(n_sfb + (6 * 3)) { channel.scalefacs[sfb] = bs.read_bits_leq32(slen2)? as u8; } bits_read += 6 * 3 * slen2 as usize; } } // Normal (long, start, end) windows... else { // For normal windows there are 21 scale factor bands. These bands are divivided into four // band ranges. Scale factors in the first two band ranges: [0..6], [6..11], have scale // factors that are slen1 bits long, while the last two band ranges: [11..16], [16..21] have // scale factors that are slen2 bits long. const SCALE_FACTOR_BANDS: [(usize, usize); 4] = [(0, 6), (6, 11), (11, 16), (16, 21)]; for (i, (start, end)) in SCALE_FACTOR_BANDS.iter().enumerate() { let slen = if i < 2 { slen1 } else { slen2 }; // If this is the second granule, and the scale factor selection information for this // channel indicates that the scale factors should be copied from the first granule, // do so. if gr > 0 && frame_data.scfsi[ch][i] { let (granule0, granule1) = frame_data.granules.split_first_mut().unwrap(); granule1[0].channels[ch].scalefacs[*start..*end] .copy_from_slice(&granule0.channels[ch].scalefacs[*start..*end]); } // Otherwise, read the scale factors from the bitstream. Since scale factors are already // zeroed out by default, don't do anything if slen is 0. else if slen > 0 { for sfb in *start..*end { frame_data.granules[gr].channels[ch].scalefacs[sfb] = bs.read_bits_leq32(slen)? as u8; } bits_read += slen as usize * (end - start); } } } Ok(bits_read as u32) } /// Reads the scale factors for a single channel in a granule in a MPEG version 2 audio frame. pub(super) fn read_scale_factors_mpeg2( bs: &mut B, is_intensity_stereo: bool, channel: &mut GranuleChannel, ) -> Result { let mut bits_read = 0; let block_index = match channel.block_type { BlockType::Short { is_mixed: true } => 2, BlockType::Short { is_mixed: false } => 1, _ => 0, }; let (slen_table, nsfb_table) = if is_intensity_stereo { // The actual value of scalefac_compress is a 9-bit unsigned integer (0..512) for MPEG2. A // left shift reduces it to an 8-bit value (0..256). let sfc = u32::from(channel.scalefac_compress) >> 1; match sfc { 0..=179 => ( [ (sfc / 36), // (sfc % 36) / 6, // (sfc % 36) % 6, // 0, // ], &SCALE_FACTOR_MPEG2_NSFB[0][block_index], ), 180..=243 => ( [ ((sfc - 180) % 64) >> 4, // ((sfc - 180) % 16) >> 2, // ((sfc - 180) % 4), // 0, // ], &SCALE_FACTOR_MPEG2_NSFB[1][block_index], ), 244..=255 => ( [ (sfc - 244) / 3, // (sfc - 244) % 3, // 0, // 0, // ], &SCALE_FACTOR_MPEG2_NSFB[2][block_index], ), _ => unreachable!(), } } else { // The actual value of scalefac_compress is a 9-bit unsigned integer (0..512) for MPEG2. let sfc = u32::from(channel.scalefac_compress); // Preflag is set only if scalefac_compress >= 500 and this is not the intensity stereo // channel. See ISO/IEC 13818-3 section 2.4.3.4. channel.preflag = sfc >= 500; match sfc { 0..=399 => ( [ (sfc >> 4) / 5, // (sfc >> 4) % 5, // (sfc % 16) >> 2, // (sfc % 4), // ], &SCALE_FACTOR_MPEG2_NSFB[3][block_index], ), 400..=499 => ( [ ((sfc - 400) >> 2) / 5, // ((sfc - 400) >> 2) % 5, // (sfc - 400) % 4, // 0, // ], &SCALE_FACTOR_MPEG2_NSFB[4][block_index], ), 500..=512 => ( [ (sfc - 500) / 3, // (sfc - 500) % 3, // 0, // 0, // ], &SCALE_FACTOR_MPEG2_NSFB[5][block_index], ), _ => unreachable!(), } }; let mut start = 0; for (&slen, &n_sfb) in slen_table.iter().zip(nsfb_table.iter()) { // If slen > 0, read n_sfb scale factors with each scale factor being slen bits long. If // slen == 0, but n_sfb > 0, then the those scale factors should be set to 0. Since all // scalefacs are preinitialized to 0, this process may be skipped. if slen > 0 { for sfb in start..(start + n_sfb) { channel.scalefacs[sfb] = bs.read_bits_leq32(slen)? as u8; } bits_read += slen * n_sfb as u32; } start += n_sfb; } Ok(bits_read) } symphonia-bundle-mp3-0.5.2/src/layer3/codebooks.rs000075500000000000000000000574511046102023000201260ustar 00000000000000// Symphonia // Copyright (c) 2019-2022 The Project Symphonia Developers. // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. use symphonia_core::io::vlc::*; use lazy_static::lazy_static; #[rustfmt::skip] const MPEG_CODES_0: [u32; 0] = [ ]; #[rustfmt::skip] const MPEG_BITS_0: [u8; 0] = [ ]; #[rustfmt::skip] const MPEG_CODES_1: [u32; 4] = [ 0x0001, 0x0001, 0x0001, 0x0000, ]; #[rustfmt::skip] const MPEG_BITS_1: [u8; 4] = [ 1, 3, 2, 3, ]; #[rustfmt::skip] const MPEG_CODES_2: [u32; 9] = [ 0x0001, 0x0002, 0x0001, 0x0003, 0x0001, 0x0001, 0x0003, 0x0002, 0x0000, ]; #[rustfmt::skip] const MPEG_BITS_2: [u8; 9] = [ 1, 3, 6, 3, 3, 5, 5, 5, 6, ]; #[rustfmt::skip] const MPEG_CODES_3: [u32; 9] = [ 0x0003, 0x0002, 0x0001, 0x0001, 0x0001, 0x0001, 0x0003, 0x0002, 0x0000, ]; #[rustfmt::skip] const MPEG_BITS_3: [u8; 9] = [ 2, 2, 6, 3, 2, 5, 5, 5, 6, ]; #[rustfmt::skip] const MPEG_CODES_5: [u32; 16] = [ 0x0001, 0x0002, 0x0006, 0x0005, 0x0003, 0x0001, 0x0004, 0x0004, 0x0007, 0x0005, 0x0007, 0x0001, 0x0006, 0x0001, 0x0001, 0x0000, ]; #[rustfmt::skip] const MPEG_BITS_5: [u8; 16] = [ 1, 3, 6, 7, 3, 3, 6, 7, 6, 6, 7, 8, 7, 6, 7, 8, ]; #[rustfmt::skip] const MPEG_CODES_6: [u32; 16] = [ 0x0007, 0x0003, 0x0005, 0x0001, 0x0006, 0x0002, 0x0003, 0x0002, 0x0005, 0x0004, 0x0004, 0x0001, 0x0003, 0x0003, 0x0002, 0x0000, ]; #[rustfmt::skip] const MPEG_BITS_6: [u8; 16] = [ 3, 3, 5, 7, 3, 2, 4, 5, 4, 4, 5, 6, 6, 5, 6, 7, ]; #[rustfmt::skip] const MPEG_CODES_7: [u32; 36] = [ 0x0001, 0x0002, 0x000a, 0x0013, 0x0010, 0x000a, 0x0003, 0x0003, 0x0007, 0x000a, 0x0005, 0x0003, 0x000b, 0x0004, 0x000d, 0x0011, 0x0008, 0x0004, 0x000c, 0x000b, 0x0012, 0x000f, 0x000b, 0x0002, 0x0007, 0x0006, 0x0009, 0x000e, 0x0003, 0x0001, 0x0006, 0x0004, 0x0005, 0x0003, 0x0002, 0x0000, ]; #[rustfmt::skip] const MPEG_BITS_7: [u8; 36] = [ 1, 3, 6, 8, 8, 9, 3, 4, 6, 7, 7, 8, 6, 5, 7, 8, 8, 9, 7, 7, 8, 9, 9, 9, 7, 7, 8, 9, 9, 10, 8, 8, 9, 10, 10, 10, ]; #[rustfmt::skip] const MPEG_CODES_8: [u32; 36] = [ 0x0003, 0x0004, 0x0006, 0x0012, 0x000c, 0x0005, 0x0005, 0x0001, 0x0002, 0x0010, 0x0009, 0x0003, 0x0007, 0x0003, 0x0005, 0x000e, 0x0007, 0x0003, 0x0013, 0x0011, 0x000f, 0x000d, 0x000a, 0x0004, 0x000d, 0x0005, 0x0008, 0x000b, 0x0005, 0x0001, 0x000c, 0x0004, 0x0004, 0x0001, 0x0001, 0x0000, ]; #[rustfmt::skip] const MPEG_BITS_8: [u8; 36] = [ 2, 3, 6, 8, 8, 9, 3, 2, 4, 8, 8, 8, 6, 4, 6, 8, 8, 9, 8, 8, 8, 9, 9, 10, 8, 7, 8, 9, 10, 10, 9, 8, 9, 9, 11, 11, ]; #[rustfmt::skip] const MPEG_CODES_9: [u32; 36] = [ 0x0007, 0x0005, 0x0009, 0x000e, 0x000f, 0x0007, 0x0006, 0x0004, 0x0005, 0x0005, 0x0006, 0x0007, 0x0007, 0x0006, 0x0008, 0x0008, 0x0008, 0x0005, 0x000f, 0x0006, 0x0009, 0x000a, 0x0005, 0x0001, 0x000b, 0x0007, 0x0009, 0x0006, 0x0004, 0x0001, 0x000e, 0x0004, 0x0006, 0x0002, 0x0006, 0x0000, ]; #[rustfmt::skip] const MPEG_BITS_9: [u8; 36] = [ 3, 3, 5, 6, 8, 9, 3, 3, 4, 5, 6, 8, 4, 4, 5, 6, 7, 8, 6, 5, 6, 7, 7, 8, 7, 6, 7, 7, 8, 9, 8, 7, 8, 8, 9, 9, ]; #[rustfmt::skip] const MPEG_CODES_10: [u32; 64] = [ 0x0001, 0x0002, 0x000a, 0x0017, 0x0023, 0x001e, 0x000c, 0x0011, 0x0003, 0x0003, 0x0008, 0x000c, 0x0012, 0x0015, 0x000c, 0x0007, 0x000b, 0x0009, 0x000f, 0x0015, 0x0020, 0x0028, 0x0013, 0x0006, 0x000e, 0x000d, 0x0016, 0x0022, 0x002e, 0x0017, 0x0012, 0x0007, 0x0014, 0x0013, 0x0021, 0x002f, 0x001b, 0x0016, 0x0009, 0x0003, 0x001f, 0x0016, 0x0029, 0x001a, 0x0015, 0x0014, 0x0005, 0x0003, 0x000e, 0x000d, 0x000a, 0x000b, 0x0010, 0x0006, 0x0005, 0x0001, 0x0009, 0x0008, 0x0007, 0x0008, 0x0004, 0x0004, 0x0002, 0x0000, ]; #[rustfmt::skip] const MPEG_BITS_10: [u8; 64] = [ 1, 3, 6, 8, 9, 9, 9, 10, 3, 4, 6, 7, 8, 9, 8, 8, 6, 6, 7, 8, 9, 10, 9, 9, 7, 7, 8, 9, 10, 10, 9, 10, 8, 8, 9, 10, 10, 10, 10, 10, 9, 9, 10, 10, 11, 11, 10, 11, 8, 8, 9, 10, 10, 10, 11, 11, 9, 8, 9, 10, 10, 11, 11, 11, ]; #[rustfmt::skip] const MPEG_CODES_11: [u32; 64] = [ 0x0003, 0x0004, 0x000a, 0x0018, 0x0022, 0x0021, 0x0015, 0x000f, 0x0005, 0x0003, 0x0004, 0x000a, 0x0020, 0x0011, 0x000b, 0x000a, 0x000b, 0x0007, 0x000d, 0x0012, 0x001e, 0x001f, 0x0014, 0x0005, 0x0019, 0x000b, 0x0013, 0x003b, 0x001b, 0x0012, 0x000c, 0x0005, 0x0023, 0x0021, 0x001f, 0x003a, 0x001e, 0x0010, 0x0007, 0x0005, 0x001c, 0x001a, 0x0020, 0x0013, 0x0011, 0x000f, 0x0008, 0x000e, 0x000e, 0x000c, 0x0009, 0x000d, 0x000e, 0x0009, 0x0004, 0x0001, 0x000b, 0x0004, 0x0006, 0x0006, 0x0006, 0x0003, 0x0002, 0x0000, ]; #[rustfmt::skip] const MPEG_BITS_11: [u8; 64] = [ 2, 3, 5, 7, 8, 9, 8, 9, 3, 3, 4, 6, 8, 8, 7, 8, 5, 5, 6, 7, 8, 9, 8, 8, 7, 6, 7, 9, 8, 10, 8, 9, 8, 8, 8, 9, 9, 10, 9, 10, 8, 8, 9, 10, 10, 11, 10, 11, 8, 7, 7, 8, 9, 10, 10, 10, 8, 7, 8, 9, 10, 10, 10, 10, ]; #[rustfmt::skip] const MPEG_CODES_12: [u32; 64] = [ 0x0009, 0x0006, 0x0010, 0x0021, 0x0029, 0x0027, 0x0026, 0x001a, 0x0007, 0x0005, 0x0006, 0x0009, 0x0017, 0x0010, 0x001a, 0x000b, 0x0011, 0x0007, 0x000b, 0x000e, 0x0015, 0x001e, 0x000a, 0x0007, 0x0011, 0x000a, 0x000f, 0x000c, 0x0012, 0x001c, 0x000e, 0x0005, 0x0020, 0x000d, 0x0016, 0x0013, 0x0012, 0x0010, 0x0009, 0x0005, 0x0028, 0x0011, 0x001f, 0x001d, 0x0011, 0x000d, 0x0004, 0x0002, 0x001b, 0x000c, 0x000b, 0x000f, 0x000a, 0x0007, 0x0004, 0x0001, 0x001b, 0x000c, 0x0008, 0x000c, 0x0006, 0x0003, 0x0001, 0x0000, ]; #[rustfmt::skip] const MPEG_BITS_12: [u8; 64] = [ 4, 3, 5, 7, 8, 9, 9, 9, 3, 3, 4, 5, 7, 7, 8, 8, 5, 4, 5, 6, 7, 8, 7, 8, 6, 5, 6, 6, 7, 8, 8, 8, 7, 6, 7, 7, 8, 8, 8, 9, 8, 7, 8, 8, 8, 9, 8, 9, 8, 7, 7, 8, 8, 9, 9, 10, 9, 8, 8, 9, 9, 9, 9, 10, ]; #[rustfmt::skip] const MPEG_CODES_13: [u32; 256] = [ 0x0001, 0x0005, 0x000e, 0x0015, 0x0022, 0x0033, 0x002e, 0x0047, 0x002a, 0x0034, 0x0044, 0x0034, 0x0043, 0x002c, 0x002b, 0x0013, 0x0003, 0x0004, 0x000c, 0x0013, 0x001f, 0x001a, 0x002c, 0x0021, 0x001f, 0x0018, 0x0020, 0x0018, 0x001f, 0x0023, 0x0016, 0x000e, 0x000f, 0x000d, 0x0017, 0x0024, 0x003b, 0x0031, 0x004d, 0x0041, 0x001d, 0x0028, 0x001e, 0x0028, 0x001b, 0x0021, 0x002a, 0x0010, 0x0016, 0x0014, 0x0025, 0x003d, 0x0038, 0x004f, 0x0049, 0x0040, 0x002b, 0x004c, 0x0038, 0x0025, 0x001a, 0x001f, 0x0019, 0x000e, 0x0023, 0x0010, 0x003c, 0x0039, 0x0061, 0x004b, 0x0072, 0x005b, 0x0036, 0x0049, 0x0037, 0x0029, 0x0030, 0x0035, 0x0017, 0x0018, 0x003a, 0x001b, 0x0032, 0x0060, 0x004c, 0x0046, 0x005d, 0x0054, 0x004d, 0x003a, 0x004f, 0x001d, 0x004a, 0x0031, 0x0029, 0x0011, 0x002f, 0x002d, 0x004e, 0x004a, 0x0073, 0x005e, 0x005a, 0x004f, 0x0045, 0x0053, 0x0047, 0x0032, 0x003b, 0x0026, 0x0024, 0x000f, 0x0048, 0x0022, 0x0038, 0x005f, 0x005c, 0x0055, 0x005b, 0x005a, 0x0056, 0x0049, 0x004d, 0x0041, 0x0033, 0x002c, 0x002b, 0x002a, 0x002b, 0x0014, 0x001e, 0x002c, 0x0037, 0x004e, 0x0048, 0x0057, 0x004e, 0x003d, 0x002e, 0x0036, 0x0025, 0x001e, 0x0014, 0x0010, 0x0035, 0x0019, 0x0029, 0x0025, 0x002c, 0x003b, 0x0036, 0x0051, 0x0042, 0x004c, 0x0039, 0x0036, 0x0025, 0x0012, 0x0027, 0x000b, 0x0023, 0x0021, 0x001f, 0x0039, 0x002a, 0x0052, 0x0048, 0x0050, 0x002f, 0x003a, 0x0037, 0x0015, 0x0016, 0x001a, 0x0026, 0x0016, 0x0035, 0x0019, 0x0017, 0x0026, 0x0046, 0x003c, 0x0033, 0x0024, 0x0037, 0x001a, 0x0022, 0x0017, 0x001b, 0x000e, 0x0009, 0x0007, 0x0022, 0x0020, 0x001c, 0x0027, 0x0031, 0x004b, 0x001e, 0x0034, 0x0030, 0x0028, 0x0034, 0x001c, 0x0012, 0x0011, 0x0009, 0x0005, 0x002d, 0x0015, 0x0022, 0x0040, 0x0038, 0x0032, 0x0031, 0x002d, 0x001f, 0x0013, 0x000c, 0x000f, 0x000a, 0x0007, 0x0006, 0x0003, 0x0030, 0x0017, 0x0014, 0x0027, 0x0024, 0x0023, 0x0035, 0x0015, 0x0010, 0x0017, 0x000d, 0x000a, 0x0006, 0x0001, 0x0004, 0x0002, 0x0010, 0x000f, 0x0011, 0x001b, 0x0019, 0x0014, 0x001d, 0x000b, 0x0011, 0x000c, 0x0010, 0x0008, 0x0001, 0x0001, 0x0000, 0x0001, ]; #[rustfmt::skip] const MPEG_BITS_13: [u8; 256] = [ 1, 4, 6, 7, 8, 9, 9, 10, 9, 10, 11, 11, 12, 12, 13, 13, 3, 4, 6, 7, 8, 8, 9, 9, 9, 9, 10, 10, 11, 12, 12, 12, 6, 6, 7, 8, 9, 9, 10, 10, 9, 10, 10, 11, 11, 12, 13, 13, 7, 7, 8, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 13, 13, 8, 7, 9, 9, 10, 10, 11, 11, 10, 11, 11, 12, 12, 13, 13, 14, 9, 8, 9, 10, 10, 10, 11, 11, 11, 11, 12, 11, 13, 13, 14, 14, 9, 9, 10, 10, 11, 11, 11, 11, 11, 12, 12, 12, 13, 13, 14, 14, 10, 9, 10, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 14, 16, 16, 9, 8, 9, 10, 10, 11, 11, 12, 12, 12, 12, 13, 13, 14, 15, 15, 10, 9, 10, 10, 11, 11, 11, 13, 12, 13, 13, 14, 14, 14, 16, 15, 10, 10, 10, 11, 11, 12, 12, 13, 12, 13, 14, 13, 14, 15, 16, 17, 11, 10, 10, 11, 12, 12, 12, 12, 13, 13, 13, 14, 15, 15, 15, 16, 11, 11, 11, 12, 12, 13, 12, 13, 14, 14, 15, 15, 15, 16, 16, 16, 12, 11, 12, 13, 13, 13, 14, 14, 14, 14, 14, 15, 16, 15, 16, 16, 13, 12, 12, 13, 13, 13, 15, 14, 14, 17, 15, 15, 15, 17, 16, 16, 12, 12, 13, 14, 14, 14, 15, 14, 15, 15, 16, 16, 19, 18, 19, 16, ]; #[rustfmt::skip] const MPEG_CODES_15: [u32; 256] = [ 0x0007, 0x000c, 0x0012, 0x0035, 0x002f, 0x004c, 0x007c, 0x006c, 0x0059, 0x007b, 0x006c, 0x0077, 0x006b, 0x0051, 0x007a, 0x003f, 0x000d, 0x0005, 0x0010, 0x001b, 0x002e, 0x0024, 0x003d, 0x0033, 0x002a, 0x0046, 0x0034, 0x0053, 0x0041, 0x0029, 0x003b, 0x0024, 0x0013, 0x0011, 0x000f, 0x0018, 0x0029, 0x0022, 0x003b, 0x0030, 0x0028, 0x0040, 0x0032, 0x004e, 0x003e, 0x0050, 0x0038, 0x0021, 0x001d, 0x001c, 0x0019, 0x002b, 0x0027, 0x003f, 0x0037, 0x005d, 0x004c, 0x003b, 0x005d, 0x0048, 0x0036, 0x004b, 0x0032, 0x001d, 0x0034, 0x0016, 0x002a, 0x0028, 0x0043, 0x0039, 0x005f, 0x004f, 0x0048, 0x0039, 0x0059, 0x0045, 0x0031, 0x0042, 0x002e, 0x001b, 0x004d, 0x0025, 0x0023, 0x0042, 0x003a, 0x0034, 0x005b, 0x004a, 0x003e, 0x0030, 0x004f, 0x003f, 0x005a, 0x003e, 0x0028, 0x0026, 0x007d, 0x0020, 0x003c, 0x0038, 0x0032, 0x005c, 0x004e, 0x0041, 0x0037, 0x0057, 0x0047, 0x0033, 0x0049, 0x0033, 0x0046, 0x001e, 0x006d, 0x0035, 0x0031, 0x005e, 0x0058, 0x004b, 0x0042, 0x007a, 0x005b, 0x0049, 0x0038, 0x002a, 0x0040, 0x002c, 0x0015, 0x0019, 0x005a, 0x002b, 0x0029, 0x004d, 0x0049, 0x003f, 0x0038, 0x005c, 0x004d, 0x0042, 0x002f, 0x0043, 0x0030, 0x0035, 0x0024, 0x0014, 0x0047, 0x0022, 0x0043, 0x003c, 0x003a, 0x0031, 0x0058, 0x004c, 0x0043, 0x006a, 0x0047, 0x0036, 0x0026, 0x0027, 0x0017, 0x000f, 0x006d, 0x0035, 0x0033, 0x002f, 0x005a, 0x0052, 0x003a, 0x0039, 0x0030, 0x0048, 0x0039, 0x0029, 0x0017, 0x001b, 0x003e, 0x0009, 0x0056, 0x002a, 0x0028, 0x0025, 0x0046, 0x0040, 0x0034, 0x002b, 0x0046, 0x0037, 0x002a, 0x0019, 0x001d, 0x0012, 0x000b, 0x000b, 0x0076, 0x0044, 0x001e, 0x0037, 0x0032, 0x002e, 0x004a, 0x0041, 0x0031, 0x0027, 0x0018, 0x0010, 0x0016, 0x000d, 0x000e, 0x0007, 0x005b, 0x002c, 0x0027, 0x0026, 0x0022, 0x003f, 0x0034, 0x002d, 0x001f, 0x0034, 0x001c, 0x0013, 0x000e, 0x0008, 0x0009, 0x0003, 0x007b, 0x003c, 0x003a, 0x0035, 0x002f, 0x002b, 0x0020, 0x0016, 0x0025, 0x0018, 0x0011, 0x000c, 0x000f, 0x000a, 0x0002, 0x0001, 0x0047, 0x0025, 0x0022, 0x001e, 0x001c, 0x0014, 0x0011, 0x001a, 0x0015, 0x0010, 0x000a, 0x0006, 0x0008, 0x0006, 0x0002, 0x0000, ]; #[rustfmt::skip] const MPEG_BITS_15: [u8; 256] = [ 3, 4, 5, 7, 7, 8, 9, 9, 9, 10, 10, 11, 11, 11, 12, 13, 4, 3, 5, 6, 7, 7, 8, 8, 8, 9, 9, 10, 10, 10, 11, 11, 5, 5, 5, 6, 7, 7, 8, 8, 8, 9, 9, 10, 10, 11, 11, 11, 6, 6, 6, 7, 7, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, 7, 6, 7, 7, 8, 8, 9, 9, 9, 9, 10, 10, 10, 11, 11, 11, 8, 7, 7, 8, 8, 8, 9, 9, 9, 9, 10, 10, 11, 11, 11, 12, 9, 7, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 11, 11, 12, 12, 9, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11, 12, 9, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 12, 12, 12, 9, 8, 9, 9, 9, 9, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 10, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11, 11, 12, 13, 12, 10, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 13, 11, 10, 9, 10, 10, 10, 11, 11, 11, 11, 11, 11, 12, 12, 13, 13, 11, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 12, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 12, 13, 12, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, ]; #[rustfmt::skip] const MPEG_CODES_16: [u32; 256] = [ 0x0001, 0x0005, 0x000e, 0x002c, 0x004a, 0x003f, 0x006e, 0x005d, 0x00ac, 0x0095, 0x008a, 0x00f2, 0x00e1, 0x00c3, 0x0178, 0x0011, 0x0003, 0x0004, 0x000c, 0x0014, 0x0023, 0x003e, 0x0035, 0x002f, 0x0053, 0x004b, 0x0044, 0x0077, 0x00c9, 0x006b, 0x00cf, 0x0009, 0x000f, 0x000d, 0x0017, 0x0026, 0x0043, 0x003a, 0x0067, 0x005a, 0x00a1, 0x0048, 0x007f, 0x0075, 0x006e, 0x00d1, 0x00ce, 0x0010, 0x002d, 0x0015, 0x0027, 0x0045, 0x0040, 0x0072, 0x0063, 0x0057, 0x009e, 0x008c, 0x00fc, 0x00d4, 0x00c7, 0x0183, 0x016d, 0x001a, 0x004b, 0x0024, 0x0044, 0x0041, 0x0073, 0x0065, 0x00b3, 0x00a4, 0x009b, 0x0108, 0x00f6, 0x00e2, 0x018b, 0x017e, 0x016a, 0x0009, 0x0042, 0x001e, 0x003b, 0x0038, 0x0066, 0x00b9, 0x00ad, 0x0109, 0x008e, 0x00fd, 0x00e8, 0x0190, 0x0184, 0x017a, 0x01bd, 0x0010, 0x006f, 0x0036, 0x0034, 0x0064, 0x00b8, 0x00b2, 0x00a0, 0x0085, 0x0101, 0x00f4, 0x00e4, 0x00d9, 0x0181, 0x016e, 0x02cb, 0x000a, 0x0062, 0x0030, 0x005b, 0x0058, 0x00a5, 0x009d, 0x0094, 0x0105, 0x00f8, 0x0197, 0x018d, 0x0174, 0x017c, 0x0379, 0x0374, 0x0008, 0x0055, 0x0054, 0x0051, 0x009f, 0x009c, 0x008f, 0x0104, 0x00f9, 0x01ab, 0x0191, 0x0188, 0x017f, 0x02d7, 0x02c9, 0x02c4, 0x0007, 0x009a, 0x004c, 0x0049, 0x008d, 0x0083, 0x0100, 0x00f5, 0x01aa, 0x0196, 0x018a, 0x0180, 0x02df, 0x0167, 0x02c6, 0x0160, 0x000b, 0x008b, 0x0081, 0x0043, 0x007d, 0x00f7, 0x00e9, 0x00e5, 0x00db, 0x0189, 0x02e7, 0x02e1, 0x02d0, 0x0375, 0x0372, 0x01b7, 0x0004, 0x00f3, 0x0078, 0x0076, 0x0073, 0x00e3, 0x00df, 0x018c, 0x02ea, 0x02e6, 0x02e0, 0x02d1, 0x02c8, 0x02c2, 0x00df, 0x01b4, 0x0006, 0x00ca, 0x00e0, 0x00de, 0x00da, 0x00d8, 0x0185, 0x0182, 0x017d, 0x016c, 0x0378, 0x01bb, 0x02c3, 0x01b8, 0x01b5, 0x06c0, 0x0004, 0x02eb, 0x00d3, 0x00d2, 0x00d0, 0x0172, 0x017b, 0x02de, 0x02d3, 0x02ca, 0x06c7, 0x0373, 0x036d, 0x036c, 0x0d83, 0x0361, 0x0002, 0x0179, 0x0171, 0x0066, 0x00bb, 0x02d6, 0x02d2, 0x0166, 0x02c7, 0x02c5, 0x0362, 0x06c6, 0x0367, 0x0d82, 0x0366, 0x01b2, 0x0000, 0x000c, 0x000a, 0x0007, 0x000b, 0x000a, 0x0011, 0x000b, 0x0009, 0x000d, 0x000c, 0x000a, 0x0007, 0x0005, 0x0003, 0x0001, 0x0003, ]; #[rustfmt::skip] const MPEG_BITS_16: [u8; 256] = [ 1, 4, 6, 8, 9, 9, 10, 10, 11, 11, 11, 12, 12, 12, 13, 9, 3, 4, 6, 7, 8, 9, 9, 9, 10, 10, 10, 11, 12, 11, 12, 8, 6, 6, 7, 8, 9, 9, 10, 10, 11, 10, 11, 11, 11, 12, 12, 9, 8, 7, 8, 9, 9, 10, 10, 10, 11, 11, 12, 12, 12, 13, 13, 10, 9, 8, 9, 9, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 9, 9, 8, 9, 9, 10, 11, 11, 12, 11, 12, 12, 13, 13, 13, 14, 10, 10, 9, 9, 10, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 14, 10, 10, 9, 10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 13, 15, 15, 10, 10, 10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 13, 14, 14, 14, 10, 11, 10, 10, 11, 11, 12, 12, 13, 13, 13, 13, 14, 13, 14, 13, 11, 11, 11, 10, 11, 12, 12, 12, 12, 13, 14, 14, 14, 15, 15, 14, 10, 12, 11, 11, 11, 12, 12, 13, 14, 14, 14, 14, 14, 14, 13, 14, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 15, 14, 14, 14, 14, 16, 11, 14, 12, 12, 12, 13, 13, 14, 14, 14, 16, 15, 15, 15, 17, 15, 11, 13, 13, 11, 12, 14, 14, 13, 14, 14, 15, 16, 15, 17, 15, 14, 11, 9, 8, 8, 9, 9, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 8, ]; #[rustfmt::skip] const MPEG_CODES_24: [u32; 256] = [ 0x000f, 0x000d, 0x002e, 0x0050, 0x0092, 0x0106, 0x00f8, 0x01b2, 0x01aa, 0x029d, 0x028d, 0x0289, 0x026d, 0x0205, 0x0408, 0x0058, 0x000e, 0x000c, 0x0015, 0x0026, 0x0047, 0x0082, 0x007a, 0x00d8, 0x00d1, 0x00c6, 0x0147, 0x0159, 0x013f, 0x0129, 0x0117, 0x002a, 0x002f, 0x0016, 0x0029, 0x004a, 0x0044, 0x0080, 0x0078, 0x00dd, 0x00cf, 0x00c2, 0x00b6, 0x0154, 0x013b, 0x0127, 0x021d, 0x0012, 0x0051, 0x0027, 0x004b, 0x0046, 0x0086, 0x007d, 0x0074, 0x00dc, 0x00cc, 0x00be, 0x00b2, 0x0145, 0x0137, 0x0125, 0x010f, 0x0010, 0x0093, 0x0048, 0x0045, 0x0087, 0x007f, 0x0076, 0x0070, 0x00d2, 0x00c8, 0x00bc, 0x0160, 0x0143, 0x0132, 0x011d, 0x021c, 0x000e, 0x0107, 0x0042, 0x0081, 0x007e, 0x0077, 0x0072, 0x00d6, 0x00ca, 0x00c0, 0x00b4, 0x0155, 0x013d, 0x012d, 0x0119, 0x0106, 0x000c, 0x00f9, 0x007b, 0x0079, 0x0075, 0x0071, 0x00d7, 0x00ce, 0x00c3, 0x00b9, 0x015b, 0x014a, 0x0134, 0x0123, 0x0110, 0x0208, 0x000a, 0x01b3, 0x0073, 0x006f, 0x006d, 0x00d3, 0x00cb, 0x00c4, 0x00bb, 0x0161, 0x014c, 0x0139, 0x012a, 0x011b, 0x0213, 0x017d, 0x0011, 0x01ab, 0x00d4, 0x00d0, 0x00cd, 0x00c9, 0x00c1, 0x00ba, 0x00b1, 0x00a9, 0x0140, 0x012f, 0x011e, 0x010c, 0x0202, 0x0179, 0x0010, 0x014f, 0x00c7, 0x00c5, 0x00bf, 0x00bd, 0x00b5, 0x00ae, 0x014d, 0x0141, 0x0131, 0x0121, 0x0113, 0x0209, 0x017b, 0x0173, 0x000b, 0x029c, 0x00b8, 0x00b7, 0x00b3, 0x00af, 0x0158, 0x014b, 0x013a, 0x0130, 0x0122, 0x0115, 0x0212, 0x017f, 0x0175, 0x016e, 0x000a, 0x028c, 0x015a, 0x00ab, 0x00a8, 0x00a4, 0x013e, 0x0135, 0x012b, 0x011f, 0x0114, 0x0107, 0x0201, 0x0177, 0x0170, 0x016a, 0x0006, 0x0288, 0x0142, 0x013c, 0x0138, 0x0133, 0x012e, 0x0124, 0x011c, 0x010d, 0x0105, 0x0200, 0x0178, 0x0172, 0x016c, 0x0167, 0x0004, 0x026c, 0x012c, 0x0128, 0x0126, 0x0120, 0x011a, 0x0111, 0x010a, 0x0203, 0x017c, 0x0176, 0x0171, 0x016d, 0x0169, 0x0165, 0x0002, 0x0409, 0x0118, 0x0116, 0x0112, 0x010b, 0x0108, 0x0103, 0x017e, 0x017a, 0x0174, 0x016f, 0x016b, 0x0168, 0x0166, 0x0164, 0x0000, 0x002b, 0x0014, 0x0013, 0x0011, 0x000f, 0x000d, 0x000b, 0x0009, 0x0007, 0x0006, 0x0004, 0x0007, 0x0005, 0x0003, 0x0001, 0x0003, ]; #[rustfmt::skip] const MPEG_BITS_24: [u8; 256] = [ 4, 4, 6, 7, 8, 9, 9, 10, 10, 11, 11, 11, 11, 11, 12, 9, 4, 4, 5, 6, 7, 8, 8, 9, 9, 9, 10, 10, 10, 10, 10, 8, 6, 5, 6, 7, 7, 8, 8, 9, 9, 9, 9, 10, 10, 10, 11, 7, 7, 6, 7, 7, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 7, 8, 7, 7, 8, 8, 8, 8, 9, 9, 9, 10, 10, 10, 10, 11, 7, 9, 7, 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 10, 7, 9, 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 7, 10, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 8, 10, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 8, 10, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11, 8, 11, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 8, 11, 10, 9, 9, 9, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 8, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 8, 11, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 8, 12, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 4, ]; const MPEG_QUADS_CODES_A: [u32; 16] = [1, 5, 4, 5, 6, 5, 4, 4, 7, 3, 6, 0, 7, 2, 3, 1]; const MPEG_QUADS_BITS_A: [u8; 16] = [1, 4, 4, 5, 4, 6, 5, 6, 4, 5, 5, 6, 5, 6, 6, 6]; const MPEG_QUADS_CODES_B: [u32; 16] = [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]; const MPEG_QUADS_BITS_B: [u8; 16] = [4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]; struct MpegTable { codes: &'static [u32], lens: &'static [u8], wrap: u16, } struct MpegQuadsTable { codes: &'static [u32], lens: &'static [u8], wrap: u16, } const MPEG_TABLES: [MpegTable; 18] = [ // Table 0 MpegTable { codes: &MPEG_CODES_0, lens: &MPEG_BITS_0, wrap: 0x0 }, // Table 1 MpegTable { codes: &MPEG_CODES_1, lens: &MPEG_BITS_1, wrap: 0x2 }, // Table 2 MpegTable { codes: &MPEG_CODES_2, lens: &MPEG_BITS_2, wrap: 0x3 }, // Table 3 MpegTable { codes: &MPEG_CODES_3, lens: &MPEG_BITS_3, wrap: 0x3 }, // Table 4 (not used) MpegTable { codes: &MPEG_CODES_0, lens: &MPEG_BITS_0, wrap: 0x0 }, // Table 5 MpegTable { codes: &MPEG_CODES_5, lens: &MPEG_BITS_5, wrap: 0x4 }, // Table 6 MpegTable { codes: &MPEG_CODES_6, lens: &MPEG_BITS_6, wrap: 0x4 }, // Table 7 MpegTable { codes: &MPEG_CODES_7, lens: &MPEG_BITS_7, wrap: 0x6 }, // Table 8 MpegTable { codes: &MPEG_CODES_8, lens: &MPEG_BITS_8, wrap: 0x6 }, // Table 9 MpegTable { codes: &MPEG_CODES_9, lens: &MPEG_BITS_9, wrap: 0x6 }, // Table 10 MpegTable { codes: &MPEG_CODES_10, lens: &MPEG_BITS_10, wrap: 0x8 }, // Table 11 MpegTable { codes: &MPEG_CODES_11, lens: &MPEG_BITS_11, wrap: 0x8 }, // Table 12 MpegTable { codes: &MPEG_CODES_12, lens: &MPEG_BITS_12, wrap: 0x8 }, // Table 13 MpegTable { codes: &MPEG_CODES_13, lens: &MPEG_BITS_13, wrap: 0x10 }, // Table 14 (not used) MpegTable { codes: &MPEG_CODES_0, lens: &MPEG_BITS_0, wrap: 0x0 }, // Table 15 MpegTable { codes: &MPEG_CODES_15, lens: &MPEG_BITS_15, wrap: 0x10 }, // Tables 16..24 (number of linbits vary) MpegTable { codes: &MPEG_CODES_16, lens: &MPEG_BITS_16, wrap: 0x10 }, // Tables 24..32 (number of linbits vary) MpegTable { codes: &MPEG_CODES_24, lens: &MPEG_BITS_24, wrap: 0x10 }, ]; const MPEG_QUADS_TABLES: [MpegQuadsTable; 2] = [ // Table A MpegQuadsTable { codes: &MPEG_QUADS_CODES_A, lens: &MPEG_QUADS_BITS_A, wrap: 0x10 }, // Table B MpegQuadsTable { codes: &MPEG_QUADS_CODES_B, lens: &MPEG_QUADS_BITS_B, wrap: 0x10 }, ]; pub const CODEBOOK_LINBITS: [u32; 32] = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 8, 10, 13, 4, 5, 6, 7, 8, 9, 11, 13, ]; fn mpeg_gen_value(i: u16, wrap: u16) -> u16 { ((i / wrap) << 4) | (i % wrap) } lazy_static! { pub static ref CODEBOOK_TABLES: [Codebook; 18] = { let mut codebooks: [Codebook; 18] = Default::default(); for (codebook, table) in codebooks.iter_mut().zip(&MPEG_TABLES) { assert!(table.codes.len() == table.lens.len()); let len = table.codes.len() as u16; // Generate values for the codebook. let values: Vec = (0..len).into_iter() .map(|i| mpeg_gen_value(i, table.wrap)) .collect(); // Generate the codebook. let mut builder = CodebookBuilder::new(BitOrder::Verbatim); *codebook = builder.make(table.codes, table.lens, &values).unwrap(); } codebooks }; } lazy_static! { pub static ref QUADS_CODEBOOK_TABLE: [Codebook; 2] = { let mut codebooks: [Codebook; 2] = Default::default(); for (codebook, table) in codebooks.iter_mut().zip(&MPEG_QUADS_TABLES) { assert!(table.codes.len() == table.lens.len()); let len = table.codes.len() as u16; // Generate values for the codebook. let values: Vec = (0..len).into_iter() .map(|i| mpeg_gen_value(i, table.wrap)) .collect(); // Generate the codebook. let mut builder = CodebookBuilder::new(BitOrder::Verbatim); *codebook = builder.make(table.codes, table.lens, &values).unwrap(); } codebooks }; } symphonia-bundle-mp3-0.5.2/src/layer3/common.rs000064400000000000000000000162761046102023000174430ustar 00000000000000// Symphonia // Copyright (c) 2019-2022 The Project Symphonia Developers. // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. /// Startng indicies of each scale factor band at various sampling rates for long blocks. pub const SFB_LONG_BANDS: [[usize; 23]; 9] = [ // 44.1 kHz, MPEG version 1, derived from ISO/IEC 11172-3 Table B.8 [ 0, 4, 8, 12, 16, 20, 24, 30, 36, 44, 52, 62, 74, 90, 110, 134, 162, 196, 238, 288, 342, 418, 576, ], // 48 kHz [ 0, 4, 8, 12, 16, 20, 24, 30, 36, 42, 50, 60, 72, 88, 106, 128, 156, 190, 230, 276, 330, 384, 576, ], // 32 kHz [ 0, 4, 8, 12, 16, 20, 24, 30, 36, 44, 54, 66, 82, 102, 126, 156, 194, 240, 296, 364, 448, 550, 576, ], // 22.050 kHz, MPEG version 2, derived from ISO/IEC 13818-3 Table B.2 [ 0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96, 116, 140, 168, 200, 238, 284, 336, 396, 464, 522, 576, ], // 24 kHz (the band starting at 332 starts at 330 in some decoders, but 332 is correct) [ 0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96, 114, 136, 162, 194, 232, 278, 332, 394, 464, 540, 576, ], // 16 kHz [ 0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96, 116, 140, 168, 200, 238, 284, 336, 396, 464, 522, 576, ], // 11.025 kHz, MPEG version 2.5 [ 0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96, 116, 140, 168, 200, 238, 284, 336, 396, 464, 522, 576, ], // 12 kHz [ 0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96, 116, 140, 168, 200, 238, 284, 336, 396, 464, 522, 576, ], // 8 kHz [ 0, 12, 24, 36, 48, 60, 72, 88, 108, 132, 160, 192, 232, 280, 336, 400, 476, 566, 568, 570, 572, 574, 576, ], ]; /// Starting indicies of each scale factor band at various sampling rates for short blocks. Each /// value must be multiplied by 3 since there are three equal length windows per short scale factor /// band. pub const SFB_SHORT_BANDS: [[usize; 40]; 9] = [ // 44.1 kHz, MPEG version 1, derived from ISO/IEC 11172-3 Table B.8 [ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 54, 60, 66, 74, 82, 90, 100, 110, 120, 132, 144, 156, 170, 184, 198, 216, 234, 252, 274, 296, 318, 348, 378, 408, 464, 520, 576, ], // 48 kHz [ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 54, 60, 66, 72, 78, 84, 94, 104, 114, 126, 138, 150, 164, 178, 192, 208, 224, 240, 260, 280, 300, 326, 352, 378, 444, 510, 576, ], // 32 kHz [ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 54, 60, 66, 74, 82, 90, 102, 114, 126, 142, 158, 174, 194, 214, 234, 260, 286, 312, 346, 380, 414, 456, 498, 540, 552, 564, 576, ], // 22.050 kHz, MPEG version 2, derived from ISO/IEC 13818-3 Table B.2 [ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 42, 48, 54, 60, 66, 72, 80, 88, 96, 106, 116, 126, 140, 154, 168, 186, 204, 222, 248, 274, 300, 332, 364, 396, 438, 480, 522, 540, 558, 576, ], // 24 kHz [ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 42, 48, 54, 62, 70, 78, 88, 98, 108, 120, 132, 144, 158, 172, 186, 204, 222, 240, 264, 288, 312, 344, 376, 408, 452, 496, 540, 552, 564, 576, ], // 16 kHz [ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 42, 48, 54, 62, 70, 78, 88, 98, 108, 120, 132, 144, 158, 172, 186, 204, 222, 240, 264, 288, 312, 342, 372, 402, 442, 482, 522, 540, 558, 576, ], // 11.025 kHz, MPEG version 2.5 [ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 42, 48, 54, 62, 70, 78, 88, 98, 108, 120, 132, 144, 158, 172, 186, 204, 222, 240, 264, 288, 312, 342, 372, 402, 442, 482, 522, 540, 558, 576, ], // 12 kHz [ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 42, 48, 54, 62, 70, 78, 88, 98, 108, 120, 132, 144, 158, 172, 186, 204, 222, 240, 264, 288, 312, 342, 372, 402, 442, 482, 522, 540, 558, 576, ], // 8 kHz [ 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 84, 96, 108, 124, 140, 156, 176, 196, 216, 240, 264, 288, 316, 344, 372, 408, 444, 480, 482, 484, 486, 488, 490, 492, 494, 496, 498, 524, 550, 576, ], ]; pub const SFB_MIXED_BANDS: [&[usize]; 9] = [ // 44.1 kHz, MPEG version 1, derived from ISO/IEC 11172-3 Table B.8 &[ 0, 4, 8, 12, 16, 20, 24, 30, // Split-point 36, 40, 44, 48, 54, 60, 66, 74, 82, 90, 100, 110, 120, 132, 144, 156, 170, 184, 198, 216, 234, 252, 274, 296, 318, 348, 378, 408, 464, 520, 576, ], // 48 kHz &[ 0, 4, 8, 12, 16, 20, 24, 30, // Split-point 36, 40, 44, 48, 54, 60, 66, 72, 78, 84, 94, 104, 114, 126, 138, 150, 164, 178, 192, 208, 224, 240, 260, 280, 300, 326, 352, 378, 444, 510, 576, ], // 32 kHz &[ 0, 4, 8, 12, 16, 20, 24, 30, // Split-point 36, 40, 44, 48, 54, 60, 66, 74, 82, 90, 102, 114, 126, 142, 158, 174, 194, 214, 234, 260, 286, 312, 346, 380, 414, 456, 498, 540, 552, 564, 576, ], // 22.050 kHz, MPEG version 2, derived from ISO/IEC 13818-3 Table B.2 &[ 0, 6, 12, 18, 24, 30, // Split-point 36, 42, 48, 54, 60, 66, 72, 80, 88, 96, 106, 116, 126, 140, 154, 168, 186, 204, 222, 248, 274, 300, 332, 364, 396, 438, 480, 522, 540, 558, 576, ], // 24 kHz &[ 0, 6, 12, 18, 24, 30, // Split-point 36, 42, 48, 54, 62, 70, 78, 88, 98, 108, 120, 132, 144, 158, 172, 186, 204, 222, 240, 264, 288, 312, 344, 376, 408, 452, 496, 540, 552, 564, 576, ], // 16 kHz &[ 0, 6, 12, 18, 24, 30, // Split-point 36, 42, 48, 54, 62, 70, 78, 88, 98, 108, 120, 132, 144, 158, 172, 186, 204, 222, 240, 264, 288, 312, 342, 372, 402, 442, 482, 522, 540, 558, 576, ], // 11.025 kHz, MPEG version 2.5 &[ 0, 6, 12, 18, 24, 30, // Split-point 36, 42, 48, 54, 62, 70, 78, 88, 98, 108, 120, 132, 144, 158, 172, 186, 204, 222, 240, 264, 288, 312, 342, 372, 402, 442, 482, 522, 540, 558, 576, ], // 12 kHz &[ 0, 6, 12, 18, 24, 30, // Split-point 36, 42, 48, 54, 62, 70, 78, 88, 98, 108, 120, 132, 144, 158, 172, 186, 204, 222, 240, 264, 288, 312, 342, 372, 402, 442, 482, 522, 540, 558, 576, ], // 8 kHz // // Note: The mixed bands for 8kHz do not follow the same pattern as the other sample rates. // There does not appear to be a consensus among other MP3 implementations either, so this is // at best an educated guess. &[ 0, 12, 24, 36, 40, 44, 48, 56, 64, 72, 84, 96, 108, 124, 140, 156, 176, 196, 216, 240, 264, 288, 316, 344, 372, 408, 444, 480, 482, 484, 486, 488, 490, 492, 494, 496, 498, 524, 550, 576, ], ]; /// The index of the first window in the first short band of a mixed block. All bands preceeding /// the switch point are long bands. pub const SFB_MIXED_SWITCH_POINT: [usize; 9] = [8, 8, 8, 6, 6, 6, 6, 6, 3]; #[derive(Debug, PartialEq)] pub enum BlockType { // Default case when window switching is off. Also the normal case when window switching is // on. Granule contains one long block. Long, Start, Short { is_mixed: bool }, End, } symphonia-bundle-mp3-0.5.2/src/layer3/hybrid_synthesis.rs000064400000000000000000000706511046102023000215420ustar 00000000000000// Symphonia // Copyright (c) 2019-2022 The Project Symphonia Developers. // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. // Justification: Some loops are better expressed without a range loop. #![allow(clippy::needless_range_loop)] use crate::common::FrameHeader; use super::{common::*, GranuleChannel}; use std::{convert::TryInto, f64}; use lazy_static::lazy_static; lazy_static! { /// Hybrid synthesesis IMDCT window coefficients for: Long, Start, Short, and End block, in that /// order. /// /// For long blocks: /// /// ```text /// W[ 0..36] = sin(PI/36.0 * (i + 0.5)) /// ``` /// /// For start blocks: /// /// ```text /// W[ 0..18] = sin(PI/36.0 * (i + 0.5)) /// W[18..24] = 1.0 /// W[24..30] = sin(PI/12.0 * ((i - 18) - 0.5)) /// W[30..36] = 0.0 /// ``` /// /// For short blocks (to be applied to each 12 sample window): /// /// ```text /// W[ 0..12] = sin(PI/12.0 * (i + 0.5)) /// W[12..36] = 0.0 /// ``` /// /// For end blocks: /// /// ```text /// W[ 0..6 ] = 0.0 /// W[ 6..12] = sin(PI/12.0 * ((i - 6) + 0.5)) /// W[12..18] = 1.0 /// W[18..36] = sin(PI/36.0 * (i + 0.5)) /// ``` static ref IMDCT_WINDOWS: [[f32; 36]; 4] = { const PI_36: f64 = f64::consts::PI / 36.0; const PI_12: f64 = f64::consts::PI / 12.0; let mut windows = [[0f32; 36]; 4]; // Window for Long blocks. for i in 0..36 { windows[0][i] = (PI_36 * (i as f64 + 0.5)).sin() as f32; } // Window for Start blocks (indicies 30..36 implictly 0.0). for i in 0..18 { windows[1][i] = (PI_36 * (i as f64 + 0.5)).sin() as f32; } for i in 18..24 { windows[1][i] = 1.0; } for i in 24..30 { windows[1][i] = (PI_12 * ((i - 18) as f64 + 0.5)).sin() as f32; } // Window for Short blocks. for i in 0..12 { windows[2][i] = (PI_12 * (i as f64 + 0.5)).sin() as f32; } // Window for End blocks (indicies 0..6 implicitly 0.0). for i in 6..12 { windows[3][i] = (PI_12 * ((i - 6) as f64 + 0.5)).sin() as f32; } for i in 12..18 { windows[3][i] = 1.0; } for i in 18..36 { windows[3][i] = (PI_36 * (i as f64 + 0.5)).sin() as f32; } windows }; } lazy_static! { /// Lookup table of cosine coefficients for half of a 12-point IMDCT. /// /// This table is derived from the general expression: /// /// ```text /// cos12[i][k] = cos(PI/24.0 * (2*i + 1 + N/2) * (2*k + 1)) /// ``` /// where: /// `N=12`, `i=N/4..3N/4`, and `k=0..N/2`. static ref IMDCT_HALF_COS_12: [[f32; 6]; 6] = { const PI_24: f64 = f64::consts::PI / 24.0; let mut cos = [[0f32; 6]; 6]; for (i, cos_i) in cos.iter_mut().enumerate() { for (k, cos_ik) in cos_i.iter_mut().enumerate() { // Only compute the middle half of the cosine lookup table (i offset by 3). let n = (2 * (i + 3) + (12 / 2) + 1) * (2 * k + 1); *cos_ik = (PI_24 * n as f64).cos() as f32; } } cos }; } lazy_static! { /// Pair of lookup tables, CS and CA, for alias reduction. /// /// As per ISO/IEC 11172-3, CS and CA are calculated as follows: /// /// ```text /// cs[i] = 1.0 / sqrt(1.0 + c[i]^2) /// ca[i] = c[i] / sqrt(1.0 + c[i]^2) /// ``` /// /// where: /// ```text /// c[i] = [ -0.6, -0.535, -0.33, -0.185, -0.095, -0.041, -0.0142, -0.0037 ] /// ``` static ref ANTIALIAS_CS_CA: ([f32; 8], [f32; 8]) = { const C: [f64; 8] = [ -0.6, -0.535, -0.33, -0.185, -0.095, -0.041, -0.0142, -0.0037 ]; let mut cs = [0f32; 8]; let mut ca = [0f32; 8]; for i in 0..8 { let sqrt = f64::sqrt(1.0 + (C[i] * C[i])); cs[i] = (1.0 / sqrt) as f32; ca[i] = (C[i] / sqrt) as f32; } (cs, ca) }; } /// Reorder samples that are part of short blocks into sub-band order. pub(super) fn reorder(header: &FrameHeader, channel: &GranuleChannel, buf: &mut [f32; 576]) { // Only short blocks are reordered. if let BlockType::Short { is_mixed } = channel.block_type { // Every short block is split into 3 equally sized windows as illustrated below (e.g. for // a short scale factor band with win_len=4): // // <- Window #1 -> <- Window #2 -> <- Window #3 -> // [ 0 | 1 | 2 | 3 ][ 4 | 5 | 6 | 7 ][ 8 | 9 | a | b ] // <----- 3 * Short Scale Factor Band Width -----> // // Reordering interleaves the samples of each window as follows: // // [ 0 | 4 | 8 | 1 | 5 | 9 | 2 | 6 | a | 3 | 7 | b ] // <---- 3 * Short Scale Factor Band Width ----> // // Basically, reordering interleaves the 3 windows the same way that 3 planar audio buffers // would be interleaved. debug_assert!(channel.rzero <= 576); // In mixed blocks, only the short bands can be re-ordered. Determine the applicable bands. let bands = if is_mixed { let switch = SFB_MIXED_SWITCH_POINT[header.sample_rate_idx]; &SFB_MIXED_BANDS[header.sample_rate_idx][switch..] } else { &SFB_SHORT_BANDS[header.sample_rate_idx] }; let start = bands[0]; // TODO: Frankly, this is wasteful... Consider swapping between two internal buffers so we // can avoid initializing this to 0 every frame. Unsafe is not allowed in codec's so this // can't be left uninitialized. let mut reorder_buf = [0f32; 576]; let mut i = start; for (((s0, s1), s2), s3) in bands.iter().zip(&bands[1..]).zip(&bands[2..]).zip(&bands[3..]).step_by(3) { // The three short sample windows. let win0 = &buf[*s0..*s1]; let win1 = &buf[*s1..*s2]; let win2 = &buf[*s2..*s3]; // Interleave the three short sample windows. // TODO: This could likely be sped up with SIMD. for ((w0, w1), w2) in win0.iter().zip(win1).zip(win2) { reorder_buf[i + 0] = *w0; reorder_buf[i + 1] = *w1; reorder_buf[i + 2] = *w2; i += 3; } } // TODO: It is possible for i to exceed rzero, does that make sense? Or should it simply // copy between [start..rzero]? Probably not... since an entire scale factor band /should/ // be processed... // Copy reordered samples from the reorder buffer to the actual sample buffer. buf[start..i].copy_from_slice(&reorder_buf[start..i]); } } /// Applies the anti-aliasing filter to sub-bands that are not part of short blocks. pub(super) fn antialias(channel: &GranuleChannel, samples: &mut [f32; 576]) { // The number of sub-bands to anti-aliasing depends on block type. let sb_end = match channel.block_type { // Short blocks are never anti-aliased. BlockType::Short { is_mixed: false } => return, // Mixed blocks have a long block span the first 36 samples (2 sub-bands). Therefore, only // anti-alias these two sub-bands. BlockType::Short { is_mixed: true } => 2 * 18, // All other block types require all 32 sub-bands to be anti-aliased. _ => 32 * 18, }; // Amortize the lazy_static fetch over the entire anti-aliasing operation. let (cs, ca): &([f32; 8], [f32; 8]) = &ANTIALIAS_CS_CA; // Anti-aliasing is performed using 8 butterfly calculations at the boundaries of ADJACENT // sub-bands. For each calculation, there are two samples: lower and upper. For each iteration, // the lower sample index advances backwards from the boundary, while the upper sample index // advances forward from the boundary. // // For example, let B(li, ui) represent the butterfly calculation where li and ui are the // indicies of the lower and upper samples respectively. If j is the index of the first sample // of a sub-band, then the iterations are as follows: // // B(j-1,j), B(j-2,j+1), B(j-3,j+2), B(j-4,j+3), B(j-5,j+4), B(j-6,j+5), B(j-7,j+6), B(j-8,j+7) // // The butterfly calculation itself can be illustrated as follows: // // * cs[i] // l0 -------o------(-)------> l1 // \ / l1 = l0 * cs[i] - u0 * ca[i] // \ / * ca[i] u1 = u0 * cs[i] + l0 * ca[i] // \ // / \ * ca[i] where: // / \ cs[i], ca[i] are constant values for iteration i, // u0 ------o------(+)-------> u1 derived from table B.9 of ISO/IEC 11172-3. // * cs[i] // // Note that all butterfly calculations only involve two samples, and all iterations are // independant of each other. This lends itself well for SIMD processing. for sb in (18..sb_end).step_by(18) { for i in 0..8 { let li = sb - 1 - i; let ui = sb + i; let lower = samples[li]; let upper = samples[ui]; samples[li] = lower * cs[i] - upper * ca[i]; samples[ui] = upper * cs[i] + lower * ca[i]; } } } /// Performs hybrid synthesis (IMDCT and windowing). pub(super) fn hybrid_synthesis( channel: &GranuleChannel, overlap: &mut [[f32; 18]; 32], samples: &mut [f32; 576], ) { // Determine the number of sub-bands to process as long blocks. Short blocks process 0 sub-bands // as long blocks, mixed blocks process the first 2 sub-bands as long blocks, and all other // block types (long, start, end) process all 32 sub-bands as long blocks. let n_long_bands = match channel.block_type { BlockType::Short { is_mixed: false } => 0, BlockType::Short { is_mixed: true } => 2, _ => 32, }; // For sub-bands that are processed as long blocks, perform the 36-point IMDCT. if n_long_bands > 0 { let mut output = [0f32; 36]; // Select the appropriate window given the block type. let window = match channel.block_type { BlockType::Start => &IMDCT_WINDOWS[1], BlockType::End => &IMDCT_WINDOWS[3], _ => &IMDCT_WINDOWS[0], }; // For each of the 32 sub-bands (18 samples each)... for sb in 0..n_long_bands { // casting to a know-size slice lets the compiler elide bounds checks let start = 18 * sb; let sub_band: &mut [f32; 18] = (&mut samples[start..(start + 18)]).try_into().unwrap(); // Perform the 36-point on the entire sub-band. imdct36::imdct36(sub_band, &mut output); // Overlap the lower half of the IMDCT output (values 0..18) with the upper values of // the IMDCT (values 18..36) of the /previous/ iteration of the IMDCT. While doing this // also apply the window. for i in 0..18 { sub_band[i] = overlap[sb][i] + (output[i] * window[i]); overlap[sb][i] = output[18 + i] * window[18 + i]; } } } // If there are any sub-bands remaining, process them as short blocks. For short blocks, the // 12-point IMDCT must be used on each window. if n_long_bands < 32 { // Select the short block window. let window = &IMDCT_WINDOWS[2]; // For each of the remaining 32 sub-bands (18 samples each)... for sb in n_long_bands..32 { // casting to a know-size slice lets the compiler elide bounds checks let start = 18 * sb; let sub_band: &mut [f32; 18] = (&mut samples[start..(start + 18)]).try_into().unwrap(); // Perform the 12-point IMDCT on each of the 3 short windows within the sub-band (6 // samples each). let mut output = [0f32; 36]; imdct12_win(sub_band, window, &mut output); // Overlap the lower half of the IMDCT output (values 0..18) with the upper values of // the IMDCT (values 18..36) of the /previous/ iteration of the IMDCT. for i in 0..18 { sub_band[i] = overlap[sb][i] + output[i]; overlap[sb][i] = output[18 + i]; } } } } /// Performs the 12-point IMDCT, and windowing for each of the 3 short windows of a short block, and /// then overlap-adds the result. fn imdct12_win(x: &[f32; 18], window: &[f32; 36], out: &mut [f32; 36]) { let cos12 = &IMDCT_HALF_COS_12; for w in 0..3 { for i in 0..3 { // Compute the 12-point IMDCT for each of the 3 short windows using a half-size IMDCT // followed by post-processing. // // In general, the IMDCT is defined as: // // (N/2)-1 // y[i] = SUM { x[k] * cos(PI/2N * (2i + 1 + N/2) * (2k + 1)) } // k=0 // // For N=12, the IMDCT becomes: // // 5 // y[i] = SUM { x[k] * cos(PI/24 * (2i + 7) * (2k + 1)) } // k=0 // // The cosine twiddle factors are easily indexable by i and k, and are therefore // pre-computed and placed into a look-up table. // // Further, y[3..0] = -y[3..6], and y[12..9] = y[6..9] which reduces the amount of work // by half. // // Therefore, it is possible to split the half-size IMDCT computation into two halves. // In the calculations below, yl is the left-half output of the half-size IMDCT, and yr // is the right-half. let yl = (x[w] * cos12[i][0]) + (x[3 * 1 + w] * cos12[i][1]) + (x[3 * 2 + w] * cos12[i][2]) + (x[3 * 3 + w] * cos12[i][3]) + (x[3 * 4 + w] * cos12[i][4]) + (x[3 * 5 + w] * cos12[i][5]); let yr = (x[w] * cos12[i + 3][0]) + (x[3 * 1 + w] * cos12[i + 3][1]) + (x[3 * 2 + w] * cos12[i + 3][2]) + (x[3 * 3 + w] * cos12[i + 3][3]) + (x[3 * 4 + w] * cos12[i + 3][4]) + (x[3 * 5 + w] * cos12[i + 3][5]); // Each adjacent 12-point IMDCT windows are overlapped and added in the output, with the // first and last 6 samples of the output always being 0. // // Each sample from the 12-point IMDCT is multiplied by the appropriate window function // as specified in ISO/IEC 11172-3. The values of the window function are pre-computed // and given by window[0..12]. // // Since there are 3 IMDCT windows (indexed by w), y[0..12] is computed 3 times. // For the purpose of the diagram below, we label these IMDCT windows as: y0[0..12], // y1[0..12], and y2[0..12], for IMDCT windows 0..3 respectively. // // Therefore, the overlap-and-add operation can be visualized as below: // // 0 6 12 18 24 30 36 // +-------------+------------+------------+------------+------------+-------------+ // | 0 | y0[..6] | y0[..6] | y1[6..] | y2[6..] | 0 | // | (6) | | + y1[6..] | + y2[..6] | | (6) | // +-------------+------------+------------+------------+------------+-------------+ // . . . . . . . // . +-------------------------+ . . . // . | IMDCT #1 (y0) | . . . // . +-------------------------+ . . . // . . +-------------------------+ . . // . . | IMDCT #2 (y1) | . . // . . +-------------------------+ . . // . . . +-------------------------+ . // . . . | IMDCT #3 (y2) | . // . . . +-------------------------+ . // . . . . . . . // // Since the 12-point IMDCT was decomposed into a half-size IMDCT and post-processing // operations, and further split into left and right halves, each iteration of this loop // produces 4 output samples. out[6 + 6 * w + 3 - i - 1] += -yl * window[3 - i - 1]; out[6 + 6 * w + i + 3] += yl * window[i + 3]; out[6 + 6 * w + i + 6] += yr * window[i + 6]; out[6 + 6 * w + 12 - i - 1] += yr * window[12 - i - 1]; } } } /// Inverts odd samples in odd sub-bands. pub fn frequency_inversion(samples: &mut [f32; 576]) { // There are 32 sub-bands spanning 576 samples: // // 0 18 36 54 72 90 108 558 576 // +-----+-----+-----+-----+-----+-----+ . . . . +------+ // s[i] = | sb0 | sb1 | sb2 | sb3 | sb4 | sb5 | . . . . | sb31 | // +-----+-----+-----+-----+-----+-----+ . . . . +------+ // // The odd sub-bands are thusly: // // sb1 -> s[ 18.. 36] // sb3 -> s[ 54.. 72] // sb5 -> s[ 90..108] // ... // sb31 -> s[558..576] // // Each odd sample in the aforementioned sub-bands must be negated. for i in (18..576).step_by(36) { // Sample negation is unrolled into a 2x4 + 1 (9) operation to improve vectorization. for j in (i..i + 16).step_by(8) { samples[j + 1] = -samples[j + 1]; samples[j + 3] = -samples[j + 3]; samples[j + 5] = -samples[j + 5]; samples[j + 7] = -samples[j + 7]; } samples[i + 18 - 1] = -samples[i + 18 - 1]; } } #[cfg(test)] mod tests { use super::imdct12_win; use super::IMDCT_WINDOWS; use std::f64; fn imdct12_analytical(x: &[f32; 6]) -> [f32; 12] { const PI_24: f64 = f64::consts::PI / 24.0; let mut result = [0f32; 12]; for i in 0..12 { let mut sum = 0.0; for k in 0..6 { sum += (x[k] as f64) * (PI_24 * ((2 * i + (12 / 2) + 1) * (2 * k + 1)) as f64).cos(); } result[i] = sum as f32; } result } #[test] fn verify_imdct12_win() { const TEST_VECTOR: [f32; 18] = [ 0.0976, 0.9321, 0.6138, 0.0857, 0.0433, 0.4855, 0.2144, 0.8488, // 0.6889, 0.2983, 0.1957, 0.7037, 0.0052, 0.0197, 0.3188, 0.5123, // 0.2994, 0.7157, ]; let window = &IMDCT_WINDOWS[2]; // The following block performs 3 analytical 12-point IMDCTs over the test vector, and then // windows and overlaps the results to generate the final result. let actual_result = { let mut actual_result = [0f32; 36]; let mut x0 = [0f32; 6]; let mut x1 = [0f32; 6]; let mut x2 = [0f32; 6]; for i in 0..6 { x0[i] = TEST_VECTOR[3 * i + 0]; x1[i] = TEST_VECTOR[3 * i + 1]; x2[i] = TEST_VECTOR[3 * i + 2]; } let imdct0 = imdct12_analytical(&x0); let imdct1 = imdct12_analytical(&x1); let imdct2 = imdct12_analytical(&x2); for i in 0..12 { actual_result[6 + i] += imdct0[i] * window[i]; actual_result[12 + i] += imdct1[i] * window[i]; actual_result[18 + i] += imdct2[i] * window[i]; } actual_result }; let mut test_result = [0f32; 36]; imdct12_win(&TEST_VECTOR, window, &mut test_result); for i in 0..36 { assert!((actual_result[i] - test_result[i]).abs() < 0.00001); } } } mod imdct36 { /// Performs an Inverse Modified Discrete Cosine Transform (IMDCT) transforming 18 /// frequency-domain input samples, into 36 time-domain output samples. /// /// This is a straight-forward implementation of the IMDCT using Szu-Wei Lee's algorithm /// published in article [1]. /// /// [1] Szu-Wei Lee, "Improved algorithm for efficient computation of the forward and backward /// MDCT in MPEG audio coder", IEEE Transactions on Circuits and Systems II: Analog and Digital /// Signal Processing, vol. 48, no. 10, pp. 990-994, 2001. /// /// https://ieeexplore.ieee.org/document/974789 pub fn imdct36(x: &[f32; 18], y: &mut [f32; 36]) { let mut dct = [0f32; 18]; dct_iv(x, &mut dct); // Mapping of DCT-IV to IMDCT // // 0 9 27 36 // +------------+------------------------+------------+ // | dct[9..18] | -dct[0..18].rev() | -dct[0..9] | // +------------+------------------------+------------+ // // where dct[] is the DCT-IV of x. // First 9 IMDCT values are values 9..18 in the DCT-IV. y[..9].copy_from_slice(&dct[9..(9 + 9)]); // Next 18 IMDCT values are negated and /reversed/ values 0..18 in the DCT-IV. for i in 9..27 { y[i] = -dct[27 - i - 1]; } // Last 9 IMDCT values are negated values 0..9 in the DCT-IV. for i in 27..36 { y[i] = -dct[i - 27]; } } /// Continutation of `imdct36`. /// /// Step 2: Mapping N/2-point DCT-IV to N/2-point SDCT-II. fn dct_iv(x: &[f32; 18], y: &mut [f32; 18]) { // Scale factors for input samples. Computed from (16). // 2 * cos(PI * (2*m + 1) / (2*36) const SCALE: [f32; 18] = [ 1.998_096_443_163_715_6, // m=0 1.982_889_722_747_620_8, // m=1 1.952_592_014_239_866_7, // m=2 1.907_433_901_496_453_9, // m=3 1.847_759_065_022_573_5, // m=4 1.774_021_666_356_443_4, // m=5 1.686_782_891_625_771_4, // m=6 1.586_706_680_582_470_6, // m=7 1.474_554_673_620_247_9, // m=8 1.351_180_415_231_320_7, // m=9 1.217_522_858_017_441_3, // m=10 1.074_599_216_693_647_8, // m=11 0.923_497_226_470_067_7, // m=12 0.765_366_864_730_179_7, // m=13 0.601_411_599_008_546_1, // m=14 0.432_879_227_876_205_8, // m=15 0.261_052_384_440_103_0, // m=16 0.087_238_774_730_672_0, // m=17 ]; let samples = [ SCALE[0] * x[0], SCALE[1] * x[1], SCALE[2] * x[2], SCALE[3] * x[3], SCALE[4] * x[4], SCALE[5] * x[5], SCALE[6] * x[6], SCALE[7] * x[7], SCALE[8] * x[8], SCALE[9] * x[9], SCALE[10] * x[10], SCALE[11] * x[11], SCALE[12] * x[12], SCALE[13] * x[13], SCALE[14] * x[14], SCALE[15] * x[15], SCALE[16] * x[16], SCALE[17] * x[17], ]; sdct_ii_18(&samples, y); y[0] /= 2.0; for i in 1..17 { y[i] = (y[i] / 2.0) - y[i - 1]; } y[17] = (y[17] / 2.0) - y[16]; } /// Continutation of `imdct36`. /// /// Step 3: Decompose N/2-point SDCT-II into two N/4-point SDCT-IIs. fn sdct_ii_18(x: &[f32; 18], y: &mut [f32; 18]) { // Scale factors for odd input samples. Computed from (23). // 2 * cos(PI * (2*m + 1) / 36) const SCALE: [f32; 9] = [ 1.992_389_396_183_491_1, // m=0 1.931_851_652_578_136_6, // m=1 1.812_615_574_073_299_9, // m=2 1.638_304_088_577_983_6, // m=3 std::f32::consts::SQRT_2, // m=4 1.147_152_872_702_092_3, // m=5 0.845_236_523_481_398_9, // m=6 0.517_638_090_205_041_9, // m=7 0.174_311_485_495_316_3, // m=8 ]; let even = [ x[0] + x[18 - 1], x[1] + x[18 - 2], x[2] + x[18 - 3], x[3] + x[18 - 4], x[4] + x[18 - 5], x[5] + x[18 - 6], x[6] + x[18 - 7], x[7] + x[18 - 8], x[8] + x[18 - 9], ]; sdct_ii_9(&even, y); let odd = [ SCALE[0] * (x[0] - x[18 - 1]), SCALE[1] * (x[1] - x[18 - 2]), SCALE[2] * (x[2] - x[18 - 3]), SCALE[3] * (x[3] - x[18 - 4]), SCALE[4] * (x[4] - x[18 - 5]), SCALE[5] * (x[5] - x[18 - 6]), SCALE[6] * (x[6] - x[18 - 7]), SCALE[7] * (x[7] - x[18 - 8]), SCALE[8] * (x[8] - x[18 - 9]), ]; sdct_ii_9(&odd, &mut y[1..]); y[3] -= y[3 - 2]; y[5] -= y[5 - 2]; y[7] -= y[7 - 2]; y[9] -= y[9 - 2]; y[11] -= y[11 - 2]; y[13] -= y[13 - 2]; y[15] -= y[15 - 2]; y[17] -= y[17 - 2]; } /// Continutation of `imdct36`. /// /// Step 4: Computation of 9-point (N/4) SDCT-II. fn sdct_ii_9(x: &[f32; 9], y: &mut [f32]) { const D: [f32; 7] = [ -1.732_050_807_568_877_2, // -sqrt(3.0) 1.879_385_241_571_816_6, // -2.0 * cos(8.0 * PI / 9.0) -0.347_296_355_333_860_8, // -2.0 * cos(4.0 * PI / 9.0) -1.532_088_886_237_956_0, // -2.0 * cos(2.0 * PI / 9.0) -0.684_040_286_651_337_8, // -2.0 * sin(8.0 * PI / 9.0) -1.969_615_506_024_416_0, // -2.0 * sin(4.0 * PI / 9.0) -1.285_575_219_373_078_5, // -2.0 * sin(2.0 * PI / 9.0) ]; let a01 = x[3] + x[5]; let a02 = x[3] - x[5]; let a03 = x[6] + x[2]; let a04 = x[6] - x[2]; let a05 = x[1] + x[7]; let a06 = x[1] - x[7]; let a07 = x[8] + x[0]; let a08 = x[8] - x[0]; let a09 = x[4] + a05; let a10 = a01 + a03; let a11 = a10 + a07; let a12 = a03 - a07; let a13 = a01 - a07; let a14 = a01 - a03; let a15 = a02 - a04; let a16 = a15 + a08; let a17 = a04 + a08; let a18 = a02 - a08; let a19 = a02 + a04; let a20 = 2.0 * x[4] - a05; let m1 = D[0] * a06; let m2 = D[1] * a12; let m3 = D[2] * a13; let m4 = D[3] * a14; let m5 = D[0] * a16; let m6 = D[4] * a17; let m7 = D[5] * a18; // Note: the cited paper has an error, a1 should be a18. let m8 = D[6] * a19; let a21 = a20 + m2; let a22 = a20 - m2; let a23 = a20 + m3; let a24 = m1 + m6; let a25 = m1 - m6; let a26 = m1 + m7; y[0] = a09 + a11; y[2] = m8 - a26; y[4] = m4 - a21; y[6] = m5; y[8] = a22 - m3; y[10] = a25 - m7; y[12] = a11 - 2.0 * a09; y[14] = a24 + m8; y[16] = a23 + m4; } #[cfg(test)] mod tests { use super::imdct36; use std::f64; fn imdct36_analytical(x: &[f32; 18]) -> [f32; 36] { let mut result = [0f32; 36]; const PI_72: f64 = f64::consts::PI / 72.0; for i in 0..36 { let mut sum = 0.0; for j in 0..18 { sum += (x[j] as f64) * (PI_72 * (((2 * i) + 1 + 18) * ((2 * j) + 1)) as f64).cos(); } result[i] = sum as f32; } result } #[test] fn verify_imdct36() { const TEST_VECTOR: [f32; 18] = [ 0.0976, 0.9321, 0.6138, 0.0857, 0.0433, 0.4855, 0.2144, 0.8488, // 0.6889, 0.2983, 0.1957, 0.7037, 0.0052, 0.0197, 0.3188, 0.5123, // 0.2994, 0.7157, ]; let mut test_result = [0f32; 36]; imdct36(&TEST_VECTOR, &mut test_result); let actual_result = imdct36_analytical(&TEST_VECTOR); for i in 0..36 { assert!((actual_result[i] - test_result[i]).abs() < 0.00001); } } } } symphonia-bundle-mp3-0.5.2/src/layer3/mod.rs000064400000000000000000000446711046102023000167320ustar 00000000000000// Symphonia // Copyright (c) 2019-2022 The Project Symphonia Developers. // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. use std::fmt; use symphonia_core::audio::{AudioBuffer, Signal}; use symphonia_core::errors::{decode_error, Error, Result}; use symphonia_core::io::{BitReaderLtr, BufReader, ReadBitsLtr, ReadBytes}; mod bitstream; mod codebooks; mod common; mod hybrid_synthesis; mod requantize; mod stereo; use crate::{common::*, synthesis}; use common::BlockType; use log::warn; /// `BitResevoir` implements the bit resevoir mechanism for main_data. Since frames have a /// deterministic length based on the bit-rate, low-complexity portions of the audio may not need /// every byte allocated to the frame. The bit resevoir mechanism allows these unused portions of /// frames to be used by future frames. pub struct BitResevoir { buf: Box<[u8]>, len: usize, consumed: usize, } impl BitResevoir { pub fn new() -> Self { BitResevoir { buf: vec![0u8; 2048].into_boxed_slice(), len: 0, consumed: 0 } } pub fn fill(&mut self, pkt_main_data: &[u8], main_data_begin: usize) -> Result { let main_data_len = pkt_main_data.len(); // The value `main_data_begin` indicates the number of bytes from the previous frame(s) to // reuse. It must always be less than or equal to maximum amount of bytes the resevoir can // hold taking into account the additional data being added to the resevoir. let main_data_end = main_data_begin + main_data_len; if main_data_end > self.buf.len() { return decode_error("mpa: invalid main_data length, will exceed resevoir buffer"); } let unread = self.len - self.consumed; // If the offset is less-than or equal to the amount of unread data in the resevoir, shift // the re-used bytes to the beginning of the resevoir, then copy the main data of the // current packet into the resevoir. let underflow = if main_data_begin <= unread { // Shift all the re-used bytes as indicated by main_data_begin to the front of the // resevoir. self.buf.copy_within(self.len - main_data_begin..self.len, 0); // Copy the new main data from the packet buffer after the re-used bytes. self.buf[main_data_begin..main_data_end].copy_from_slice(pkt_main_data); self.len = main_data_end; 0 } else { // Shift all the unread bytes to the front of the resevoir. Since this is an underflow // condition, all unread bytes will be unconditionally reused. self.buf.copy_within(self.len - unread..self.len, 0); // If the offset is greater than the amount of data in the resevoir, then the stream is // malformed. This can occur if the decoder is starting in the middle of a stream. This // is particularly common with online radio streams. In this case, copy the main data // of the current packet into the resevoir, then return the number of bytes that are // missing. self.buf[unread..unread + main_data_len].copy_from_slice(pkt_main_data); self.len = unread + main_data_len; // The number of bytes that will be missing. let underflow = (main_data_begin - unread) as u32; warn!("mpa: invalid main_data_begin, underflow by {} bytes", underflow); underflow }; self.consumed = 0; Ok(underflow) } pub fn consume(&mut self, len: usize) { self.consumed = self.len.min(self.consumed + len); } pub fn bytes_ref(&self) -> &[u8] { &self.buf[self.consumed..self.len] } pub fn clear(&mut self) { self.len = 0; self.consumed = 0; } } /// `FrameData` contains the side_info and main_data portions of a MPEG audio frame. #[derive(Default, Debug)] struct FrameData { /// The byte offset into the bit resevoir indicating the location of the first bit of main_data. /// If 0, main_data begins after the side_info of this frame. main_data_begin: u16, /// Scale factor selector information, per channel. Each channel has 4 groups of bands that may /// be scaled in each granule. Scale factors may optionally be used by both granules to save /// bits. Bands that share scale factors for both granules are indicated by a true. Otherwise, /// each granule must store its own set of scale factors. /// /// Mapping of array indicies to bands [0..6, 6..11, 11..16, 16..21]. scfsi: [[bool; 4]; 2], /// The granules. granules: [Granule; 2], } impl FrameData { /// Get a mutable slice to the granule(s) in side_info. For MPEG1, a slice of 2 granules are /// returned. For MPEG2/2.5, a single granule slice is returned. #[inline(always)] fn granules_mut(&mut self, version: MpegVersion) -> &mut [Granule] { match version { MpegVersion::Mpeg1 => &mut self.granules[..2], _ => &mut self.granules[..1], } } } #[derive(Default, Debug)] struct Granule { /// Channels in the granule. channels: [GranuleChannel; 2], } struct GranuleChannel { /// Total number of bits used for scale factors (part2) and Huffman encoded data (part3). part2_3_length: u16, /// HALF the number of samples in the big_values partition (sum of all samples in /// `region[0..3]`). big_values: u16, /// Logarithmic quantization step size. global_gain: u8, /// Depending on the MPEG version, `scalefac_compress` determines how many bits are allocated /// per scale factor. /// /// - For MPEG1 bitstreams, `scalefac_compress` is a 4-bit index into /// `SCALE_FACTOR_SLEN[0..16]` to obtain a number of bits per scale factor pair. /// /// - For MPEG2/2.5 bitstreams, `scalefac_compress` is a 9-bit value that decodes into /// `slen[0..3]` (referred to as slen1-4 in the standard) for the number of bits per scale /// factor, and depending on which range the value falls into, for which bands. scalefac_compress: u16, /// Indicates the block type (type of window) for the channel in the granule. block_type: BlockType, /// Gain factors for region[0..3] in big_values. Each gain factor has a maximum value of 7 /// (3 bits). subblock_gain: [u8; 3], /// The Huffman table to use for decoding `region[0..3]` of big_values. table_select: [u8; 3], /// The index of the first sample in region1 of big_values. region1_start: usize, /// The index of the first sample in region2 of big_values. region2_start: usize, /// Indicates if the pre-emphasis amount for each scale factor band should be added on to each /// scale factor before requantization. preflag: bool, /// A 0.5x (false) or 1x (true) multiplier for scale factors. scalefac_scale: bool, /// Use Huffman Quads table A (0) or B (1), for decoding the count1 partition. count1table_select: u8, /// Long (scalefac_l) and short (scalefac_s) window scale factor bands. Must be interpreted /// based on the block type of the granule. /// /// For `block_type == BlockType::Short { is_mixed: false }`: /// - `scalefac_s[0..36]` -> `scalefacs[0..36]` /// /// For `block_type == BlockType::Short { is_mixed: true }`: /// - `scalefac_l[0..8]` -> `scalefacs[0..8]` /// - `scalefac_s[0..27]` -> `scalefacs[8..35]` /// /// For `block_type != BlockType::Short { .. }`: /// - `scalefac_l[0..21]` -> `scalefacs[0..21]` /// /// Note: The standard doesn't explicitly call it out, but for Short blocks, there are three /// additional scale factors, `scalefacs[36..39]`, that are always 0 and are not /// transmitted in the bitstream. /// /// For MPEG1, and MPEG2 without intensity stereo coding, a scale factor will not exceed 4 bits /// in length (maximum value 15). For MPEG2 with intensity stereo, a scale factor will not /// exceed 5 bits (maximum value 31) in length. scalefacs: [u8; 39], /// The starting sample index of the rzero partition, or the count of big_values and count1 /// samples. rzero: usize, } impl Default for GranuleChannel { fn default() -> Self { GranuleChannel { part2_3_length: 0, big_values: 0, global_gain: 0, scalefac_compress: 0, block_type: BlockType::Long, subblock_gain: [0; 3], table_select: [0; 3], region1_start: 0, region2_start: 0, preflag: false, scalefac_scale: false, count1table_select: 0, scalefacs: [0; 39], rzero: 0, } } } impl fmt::Debug for GranuleChannel { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { writeln!(f, "GranuleChannel {{")?; writeln!(f, "\tpart2_3_length={}", self.part2_3_length)?; writeln!(f, "\tbig_values={}", self.big_values)?; writeln!(f, "\tglobal_gain={}", self.global_gain)?; writeln!(f, "\tscalefac_compress={}", self.scalefac_compress)?; writeln!(f, "\tblock_type={:?}", self.block_type)?; writeln!(f, "\tsubblock_gain={:?}", self.subblock_gain)?; writeln!(f, "\ttable_select={:?}", self.table_select)?; writeln!(f, "\tregion1_start={}", self.region1_start)?; writeln!(f, "\tregion2_start={}", self.region2_start)?; writeln!(f, "\tpreflag={}", self.preflag)?; writeln!(f, "\tscalefac_scale={}", self.scalefac_scale)?; writeln!(f, "\tcount1table_select={}", self.count1table_select)?; write!(f, "\tscalefacs=[ ")?; for sf in &self.scalefacs[..] { write!(f, "{}, ", sf)?; } writeln!(f, "]")?; writeln!(f, "\trzero={}", self.rzero)?; writeln!(f, "}}") } } pub struct Layer3 { pub samples: [[[f32; 576]; 2]; 2], pub overlap: [[[f32; 18]; 32]; 2], pub synthesis: [synthesis::SynthesisState; 2], pub resevoir: BitResevoir, } impl Layer3 { pub fn new() -> Self { Self { samples: [[[0f32; 576]; 2]; 2], overlap: [[[0f32; 18]; 32]; 2], synthesis: Default::default(), resevoir: BitResevoir::new(), } } /// Reads the main_data portion of a MPEG audio frame from a `BitStream` into `FrameData`. fn read_main_data( &mut self, header: &FrameHeader, underflow_bits: u32, frame_data: &mut FrameData, ) -> Result { let main_data = self.resevoir.bytes_ref(); let mut part2_3_begin = 0; let mut part2_3_skipped = 0; for gr in 0..header.n_granules() { // If the resevoir underflowed (i.e., main_data_begin references bits not present in the // resevoir) then skip the granule(s) the missing bits would belong to. if part2_3_skipped < underflow_bits { // Zero the samples in the granule channel(s) and sum the part2/3 bits that were // skipped. for ch in 0..header.n_channels() { requantize::zero(&mut self.samples[gr][ch]); part2_3_skipped += u32::from(frame_data.granules[gr].channels[ch].part2_3_length); } // Adjust the start position of the next granule in the buffer of main data that is // available. if part2_3_skipped > underflow_bits { part2_3_begin = (part2_3_skipped - underflow_bits) as usize; } // Continue at the next granule. continue; } for ch in 0..header.n_channels() { let byte_index = part2_3_begin >> 3; // Create a bit reader at the expected starting bit position. let mut bs = if byte_index < main_data.len() { let mut bs = BitReaderLtr::new(&main_data[byte_index..]); let bit_index = part2_3_begin & 0x7; if bit_index > 0 { bs.ignore_bits(bit_index as u32)?; } bs } else { return decode_error("mpa: invalid main_data offset"); }; // Read the scale factors (part2) and get the number of bits read. let part2_len = if header.is_mpeg1() { bitstream::read_scale_factors_mpeg1(&mut bs, gr, ch, frame_data) } else { bitstream::read_scale_factors_mpeg2( &mut bs, ch > 0 && header.is_intensity_stereo(), &mut frame_data.granules[gr].channels[ch], ) }?; let part2_3_length = u32::from(frame_data.granules[gr].channels[ch].part2_3_length); // The part2 length must be less than or equal to the part2_3_length. if part2_len > part2_3_length { return decode_error("mpa: part2_3_length is not valid"); } // The Huffman code length (part3). let part3_len = part2_3_length - part2_len; // Decode the Huffman coded spectral samples and get the starting index of the rzero // partition. let huffman_result = requantize::read_huffman_samples( &mut bs, &frame_data.granules[gr].channels[ch], part3_len, &mut self.samples[gr][ch], ); // Huffman decoding errors are returned as an IO error by the bit reader. IO errors // are unrecoverable, which is not the case for huffman decoding errors. Convert the // IO error to a decode error. frame_data.granules[gr].channels[ch].rzero = match huffman_result { Ok(rzero) => rzero, Err(Error::IoError(e)) if e.kind() == std::io::ErrorKind::Other => { return decode_error("mpa: huffman decode overrun"); } Err(err) => return Err(err), }; part2_3_begin += part2_3_length as usize; } } Ok((part2_3_begin + 7) >> 3) } } impl Layer for Layer3 { fn decode( &mut self, reader: &mut BufReader<'_>, header: &FrameHeader, out: &mut AudioBuffer, ) -> Result<()> { // Initialize an empty FrameData to store the side_info and main_data portions of the // frame. let mut frame_data: FrameData = Default::default(); let _crc = if header.has_crc { Some(reader.read_be_u16()?) } else { None }; let buf = reader.read_buf_bytes_available_ref(); let mut bs = BitReaderLtr::new(buf); // Read side_info into the frame data. // TODO: Use a MonitorStream to compute the CRC. let side_info_len = match bitstream::read_side_info(&mut bs, header, &mut frame_data) { Ok(len) => len, Err(e) => { // A failure in reading this packet will cause a discontinuity in the codec // bitstream. Therefore, clear the bit reservoir since it will not be valid for the // next packet. self.resevoir.clear(); return Err(e); } }; // Buffer main data into the bit resevoir. let underflow = self.resevoir.fill(&buf[side_info_len..], frame_data.main_data_begin as usize)?; // Read the main data (scale factors and spectral samples). match self.read_main_data(header, 8 * underflow, &mut frame_data) { Ok(len) => { // Consume the bytes of main data read from the resevoir. self.resevoir.consume(len); } Err(e) => { // The bit reservoir was likely filled with invalid data. Clear it for the next // packet. self.resevoir.clear(); return Err(e); } } for gr in 0..header.n_granules() { let granule = &mut frame_data.granules[gr]; // Requantize all non-zero (big_values and count1 partition) spectral samples. requantize::requantize(header, &granule.channels[0], &mut self.samples[gr][0]); // If there is a second channel... if header.channel_mode != ChannelMode::Mono { // Requantize all non-zero spectral samples in the second channel. requantize::requantize(header, &granule.channels[1], &mut self.samples[gr][1]); // Apply joint stereo processing if it is used. stereo::stereo(header, granule, &mut self.samples[gr])?; } // Each granule will yield 576 samples. After reserving frames, all steps must be // infalliable. out.render_reserved(Some(576)); // The next steps are independant of channel count. for ch in 0..header.n_channels() { // Reorder the spectral samples in short blocks into sub-band order. hybrid_synthesis::reorder(header, &granule.channels[ch], &mut self.samples[gr][ch]); // Apply the anti-aliasing filter to all block types other than short. hybrid_synthesis::antialias(&granule.channels[ch], &mut self.samples[gr][ch]); // Perform hybrid-synthesis (IMDCT and windowing). hybrid_synthesis::hybrid_synthesis( &granule.channels[ch], &mut self.overlap[ch], &mut self.samples[gr][ch], ); // Invert every second sample in every second sub-band to negate the frequency // inversion of the polyphase filterbank. hybrid_synthesis::frequency_inversion(&mut self.samples[gr][ch]); // Perform polyphase synthesis and generate PCM samples. let out_ch_samples = out.chan_mut(ch); synthesis::synthesis( &mut self.synthesis[ch], 18, &self.samples[gr][ch], &mut out_ch_samples[(gr * 576)..((gr + 1) * 576)], ); } } Ok(()) } } symphonia-bundle-mp3-0.5.2/src/layer3/requantize.rs000075500000000000000000000352761046102023000203460ustar 00000000000000// Symphonia // Copyright (c) 2019-2022 The Project Symphonia Developers. // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. use symphonia_core::errors::Result; use symphonia_core::io::ReadBitsLtr; use crate::common::FrameHeader; use super::{codebooks, common::*, GranuleChannel}; use std::cmp::min; use std::{f32, f64}; use lazy_static::lazy_static; use log::info; lazy_static! { /// Lookup table for computing x(i) = s(i)^(4/3) where s(i) is a decoded Huffman sample. The /// value of s(i) is bound between 0..8207. static ref REQUANTIZE_POW43: [f32; 8207] = { // It is wasteful to initialize to 0.. however, Symphonia policy is to limit unsafe code to // only symphonia-core. // // TODO: Implement generic lookup table initialization in the core library. let mut pow43 = [0f32; 8207]; for (i, pow43) in pow43.iter_mut().enumerate() { *pow43 = f32::powf(i as f32, 4.0 / 3.0); } pow43 }; } /// Zero a sample buffer. #[inline(always)] pub(super) fn zero(buf: &mut [f32; 576]) { for s in buf.iter_mut() { *s = 0.0; } } /// Reads the Huffman coded spectral samples for a given channel in a granule from a `BitStream` /// into a provided sample buffer. Returns the number of decoded samples (the starting index of the /// rzero partition). /// /// Note, each spectral sample is raised to the (4/3)-rd power. This is not actually part of the /// Huffman decoding process, but, by converting the integer sample to floating point here we don't /// need to do pointless casting or use an extra buffer. pub(super) fn read_huffman_samples( bs: &mut B, channel: &GranuleChannel, part3_bits: u32, buf: &mut [f32; 576], ) -> Result { // If there are no Huffman code bits, zero all samples and return immediately. if part3_bits == 0 { zero(buf); return Ok(0); } // Dereference the POW43 table once per granule since there is a tiny overhead each time a // lazy_static is dereferenced that should be amortized over as many samples as possible. let pow43_table: &[f32; 8207] = &REQUANTIZE_POW43; let mut bits_read = 0; let mut i = 0; // There are two samples per big_value, therefore multiply big_values by 2 to get number of // samples in the big_value partition. let big_values_len = 2 * channel.big_values as usize; // There are up-to 3 regions in the big_value partition. Determine the sample index denoting the // end of each region (non-inclusive). Clamp to the end of the big_values partition. let regions: [usize; 3] = [ min(channel.region1_start, big_values_len), min(channel.region2_start, big_values_len), min(576, big_values_len), ]; // Iterate over each region in big_values. for (region_idx, region_end) in regions.iter().enumerate() { // Select the Huffman table based on the region's table select value. let table_select = channel.table_select[region_idx] as usize; // Tables 0..16 are all unique, while tables 16..24 and 24..32 each use one table but // differ in the number of linbits to use. let codebook = match table_select { 0..=15 => &codebooks::CODEBOOK_TABLES[table_select], 16..=23 => &codebooks::CODEBOOK_TABLES[16], 24..=31 => &codebooks::CODEBOOK_TABLES[17], _ => unreachable!(), }; let linbits = codebooks::CODEBOOK_LINBITS[table_select]; // If the table for a region is empty, fill the region with zeros and move on to the next // region. if codebook.is_empty() { while i < *region_end { buf[i] = 0.0; i += 1; buf[i] = 0.0; i += 1; } continue; } // Otherwise, read the big_values. while i < *region_end && bits_read < part3_bits { // Decode the next Huffman code. let (value, code_len) = bs.read_codebook(codebook)?; bits_read += code_len; // In the big_values partition, each Huffman code decodes to two sample, x and y. Each // sample being 4-bits long. let mut x = (value >> 4) as usize; let mut y = (value & 0xf) as usize; // If the first sample, x, is not 0, further process it. if x > 0 { // If x is saturated (it is at the maximum possible value), and the table specifies // linbits, then read linbits more bits and add it to the sample. if x == 15 && linbits > 0 { x += bs.read_bits_leq32(linbits)? as usize; bits_read += linbits; } // The next bit is the sign bit. If the sign bit is 1, then the sample should be // negative. The value of the sample is raised to the (4/3) power. buf[i] = (1.0 - 2.0 * bs.read_bit()? as f32) * pow43_table[x]; bits_read += 1; } else { buf[i] = 0.0; } i += 1; // Likewise, repeat the previous two steps for the second sample, y. if y > 0 { if y == 15 && linbits > 0 { y += bs.read_bits_leq32(linbits)? as usize; bits_read += linbits; } buf[i] = (1.0 - 2.0 * bs.read_bit()? as f32) * pow43_table[y]; bits_read += 1; } else { buf[i] = 0.0; } i += 1; } } let count1_codebook = &codebooks::QUADS_CODEBOOK_TABLE[usize::from(channel.count1table_select)]; // Read the count1 partition. while i <= 572 && bits_read < part3_bits { // In the count1 partition, each Huffman code decodes to 4 samples: v, w, x, and y. // Each sample is 1-bit long (1 or 0). // // For each 1-bit sample, if it is 0, then the dequantized sample value is 0 as well. If // the 1-bit sample is 1, then a sign bit is read. The dequantized sample is then either // +/-1.0 depending on the sign bit. // Decode the next Huffman code. let (value, code_len) = bs.read_codebook(count1_codebook)?; bits_read += code_len; // The first 4 bits indicate if a sample if 0 or 1. Count the number of samples with a // non-zero value. let num_ones = (value & 0xf).count_ones(); // Read the sign bits for each non-zero sample in a single read. let mut signs = bs.read_bits_leq32(num_ones)?; bits_read += num_ones; // Unpack the samples. if value & 0x1 != 0 { buf[i + 3] = 1.0 - 2.0 * (signs & 1) as f32; signs >>= 1; } else { buf[i + 3] = 0.0; } if value & 0x2 != 0 { buf[i + 2] = 1.0 - 2.0 * (signs & 1) as f32; signs >>= 1; } else { buf[i + 2] = 0.0; } if value & 0x4 != 0 { buf[i + 1] = 1.0 - 2.0 * (signs & 1) as f32; signs >>= 1; } else { buf[i + 1] = 0.0; } if value & 0x8 != 0 { buf[i + 0] = 1.0 - 2.0 * (signs & 1) as f32; } else { buf[i + 0] = 0.0; } i += 4; } // Ignore any extra "stuffing" bits. if bits_read < part3_bits { bs.ignore_bits(part3_bits - bits_read)?; } // Word on the street is that some encoders are poor at "stuffing" bits, resulting in part3_len // being ever so slightly too large. This causes the Huffman decode loop to decode the next few // bits as spectral samples. However, these bits are actually random data and are not real // samples, therefore, undo them! The caller will be reponsible for re-aligning the bitstream // reader. Candy Pop confirms this. else if bits_read > part3_bits && i > big_values_len { info!("count1 overrun, malformed bitstream"); i -= 4; } else if bits_read > part3_bits { // It seems that most other decoders don't undo overruns of the big values. We'll just print // a message for now. info!("big_values overrun, malformed bitstream"); } // The final partition after the count1 partition is the rzero partition. Samples in this // partition are all 0. for j in (i..576).step_by(2) { buf[j + 0] = 0.0; buf[j + 1] = 0.0; } Ok(i) } /// Requantize long block samples in `buf`. fn requantize_long(channel: &GranuleChannel, bands: &[usize], buf: &mut [f32; 576]) { // For long blocks dequantization and scaling is governed by the following equation: // // xr(i) = s(i)^(4/3) * 2^(0.25*A) * 2^(-B) // where: // s(i) is the decoded Huffman sample // xr(i) is the dequantized sample // and: // A = global_gain[gr] - 210 // B = scalefac_multiplier * (scalefacs[gr][ch][sfb] + (preflag[gr] * pretab[sfb])) // // Note: The samples in buf are the result of s(i)^(4/3) for each sample i. debug_assert!(bands.len() <= 23); // The preemphasis table is from table B.6 in ISO/IEC 11172-3. const PRE_EMPHASIS: [u8; 22] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 3, 2, 0]; // Calculate A, it is constant for the entire requantization. let a = i32::from(channel.global_gain) - 210; let scalefac_shift = if channel.scalefac_scale { 2 } else { 1 }; // Requantize each scale-factor band in buf. for (i, (start, end)) in bands.iter().zip(&bands[1..]).enumerate() { // Do not requantize bands starting after the rzero sample since all samples from there on // are 0. if *start >= channel.rzero { break; } // Lookup the pre-emphasis amount if required. let pre_emphasis = if channel.preflag { PRE_EMPHASIS[i] } else { 0 }; // Calculate B. let b = i32::from((channel.scalefacs[i] + pre_emphasis) << scalefac_shift); // Calculate 2^(0.25*A) * 2^(-B). This can be rewritten as 2^{ 0.25 * (A - 4 * B) }. // Since scalefac_shift was multiplies by 4 above, the final equation becomes // 2^{ 0.25 * (A - B) }. let pow2ab = f64::powf(2.0, 0.25 * f64::from(a - b)) as f32; // Calculate the ending sample index for the scale-factor band, clamping it to the length of // the sample buffer. let band_end = min(*end, channel.rzero); // The sample buffer contains s(i)^(4/3), now multiply in 2^(0.25*A) * 2^(-B) to get xr(i). for sample in &mut buf[*start..band_end] { *sample *= pow2ab; } } } /// Requantize short block samples in `buf` starting at scale-factor band `sfb_init`. fn requantize_short( channel: &GranuleChannel, bands: &[usize], switch: usize, buf: &mut [f32; 576], ) { // For short blocks dequantization and scaling is governed by the following equation: // // xr(i) = s(i)^(4/3) * 2^(0.25*A) * 2^(-B) // where: // s(i) is the decoded Huffman sample // xr(i) is the dequantized sample // and: // A = global_gain[gr] - 210 - (8 * subblock_gain[gr][win]) // B = scalefac_multiplier * scalefacs[gr][ch][sfb][win] // // Note: The samples in buf are the result of s(i)^(4/3) for each sample i. debug_assert!(bands.len() <= 40); // Calculate the window-independant part of A: global_gain[gr] - 210. let gain = i32::from(channel.global_gain) - 210; // Calculate A for each window. let a = [ gain - 8 * i32::from(channel.subblock_gain[0]), gain - 8 * i32::from(channel.subblock_gain[1]), gain - 8 * i32::from(channel.subblock_gain[2]), ]; // Likweise, the scalefac_multiplier is constant for the granule. The actual scale is multiplied // by 4 to combine the two pow2 operations into one by adding the exponents. The sum of the // exponent is multiplied by 0.25 so B must be multiplied by 4 to counter the quartering. A // bitshift operation is used for the actual multiplication, so scalefac_multiplier is named // scalefac_shift in this case. let scalefac_shift = if channel.scalefac_scale { 2 } else { 1 }; for (i, (start, end)) in bands.iter().zip(&bands[1..]).enumerate() { // Do not requantize bands starting after the rzero sample since all samples from there on // are 0. if *start >= channel.rzero { break; } // Calculate B. let b = i32::from(channel.scalefacs[switch + i] << scalefac_shift); // Calculate 2^(0.25*A) * 2^(-B). This can be rewritten as 2^{ 0.25 * (A - 4 * B) }. // Since scalefac_shift multiplies by 4 above, the final equation becomes // 2^{ 0.25 * (A - B) }. let pow2ab = f64::powf(2.0, 0.25 * f64::from(a[i % 3] - b)) as f32; // Clamp the ending sample index to the rzero sample index. Since samples starting from // rzero are 0, there is no point in requantizing them. let win_end = min(*end, channel.rzero); // The sample buffer contains s(i)^(4/3), now multiply in 2^(0.25*A) * 2^(-B) to get // xr(i). for sample in &mut buf[*start..win_end] { *sample *= pow2ab; } } } /// Requantize samples in `buf` regardless of block type. pub(super) fn requantize(header: &FrameHeader, channel: &GranuleChannel, buf: &mut [f32; 576]) { match channel.block_type { BlockType::Short { is_mixed: false } => { requantize_short(channel, &SFB_SHORT_BANDS[header.sample_rate_idx], 0, buf); } BlockType::Short { is_mixed: true } => { // A mixed block is a combination of a long block and short blocks. The first few scale // factor bands, and thus samples, belong to a single long block, while the remaining // bands and samples belong to short blocks. Therefore, requantization for mixed blocks // can be decomposed into short and long block requantizations. // // As per ISO/IEC 11172-3, the short scale factor band at which the long block ends and // the short blocks begin is denoted by switch_point_s. let bands = SFB_MIXED_BANDS[header.sample_rate_idx]; let switch = SFB_MIXED_SWITCH_POINT[header.sample_rate_idx]; requantize_long(channel, &bands[..switch], buf); requantize_short(channel, &bands[switch..], switch, buf); } _ => { requantize_long(channel, &SFB_LONG_BANDS[header.sample_rate_idx], buf); } } } symphonia-bundle-mp3-0.5.2/src/layer3/stereo.rs000064400000000000000000000511071046102023000174440ustar 00000000000000// Symphonia // Copyright (c) 2019-2022 The Project Symphonia Developers. // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. use symphonia_core::errors::{decode_error, Result}; use crate::common::{ChannelMode, FrameHeader, Mode}; use super::{common::*, Granule}; use std::cmp::max; use std::{f32, f64}; use lazy_static::lazy_static; /// The invalid intensity position for MPEG1 bitstreams. const INTENSITY_INV_POS_MPEG1: u8 = 7; /// The invalid intensity position for MPEG2 and MPEG2.5 bitstreams. /// /// NOTE: Some decoders also consider 7 to be an invalid intensity position in MPEG2 and MPEG2.5. /// However, this appears wrong. According to the standard, the /maximum/ value for the intensity /// position is considered invalid. For MPEG1, since the intensity ratios are only specified for /// is_pos < 7. For MPEG2 the ratios are specified for is_pos < 31. Therefore, it doesn't make sense /// to consider is_pos == 7 invalid for MPEG2 or 2.5. const INTENSITY_INV_POS_MPEG2: u8 = 31; lazy_static! { /// (Left, right) channel coefficients for decoding intensity stereo in MPEG2 bitstreams. /// /// These coefficients are derived from section 2.4.3.2 of ISO/IEC 13818-3. /// /// As per the specification, for a given intensity position, is_pos (0 <= is_pos < 32), the /// channel coefficients, k_l and k_r, may be calculated as per the table below: /// /// ```text /// If... | k_l | k_r /// -----------------+-------------------------+------------------- /// is_pos == 0 | 1.0 | 1.0 /// is_pos & 1 == 1 | i0 ^ [(is_pos + 1) / 2] | 1.0 /// is_pos & 1 == 0 | 1.0 | i0 ^ (is_pos / 2) /// ``` /// /// The value of i0 is dependant on the least significant bit of scalefac_compress. /// /// ```text /// scalefac_compress & 1 | i0 /// ----------------------+--------------------- /// 0 | 1 / sqrt(sqrt(2.0)) /// 1 | 1 / sqrt(2.0) /// ``` /// /// The first dimension of this table is indexed by scalefac_compress & 1 to select i0. The /// second dimension is indexed by is_pos to obtain the channel coefficients. Note that /// is_pos == 31 is considered an invalid position, but IS included in the table. static ref INTENSITY_STEREO_RATIOS_MPEG2: [[(f32, f32); 32]; 2] = { let is_scale: [f64; 2] = [ 1.0 / f64::sqrt(f64::consts::SQRT_2), f64::consts::FRAC_1_SQRT_2, ]; let mut ratios = [[(0.0, 0.0); 32]; 2]; for (i, is_pos) in (0..32).enumerate() { if is_pos & 1 != 0 { // Odd case. ratios[0][i] = (is_scale[0].powf(f64::from(is_pos + 1) / 2.0) as f32, 1.0); ratios[1][i] = (is_scale[1].powf(f64::from(is_pos + 1) / 2.0) as f32, 1.0); } else { // Even & zero case. ratios[0][i] = (1.0, is_scale[0].powf(f64::from(is_pos) / 2.0) as f32); ratios[1][i] = (1.0, is_scale[1].powf(f64::from(is_pos) / 2.0) as f32); } } ratios }; } lazy_static! { /// (Left, right) channel coeffcients for decoding intensity stereo in MPEG1 bitstreams. /// /// These coefficients are derived from section 2.4.3.4.9.3 of ISO/IEC 11172-3. /// /// As per the specification, for a given intensity position, is_pos (0 <= is_pos < 7), a ratio, /// is_ratio, is calculated as follows: /// /// ```text /// is_ratio = tan(is_pos * PI/12) /// ``` /// /// Then, the channel coefficients, k_l and k_r, are calculated as follows: /// /// ```text /// k_l = is_ratio / (1 + is_ratio) /// k_r = 1 / (1 + is_ratio) /// ``` /// /// This table is indexed by is_pos. Note that is_pos == 7 is invalid and is NOT included in the /// table. static ref INTENSITY_STEREO_RATIOS_MPEG1: [(f32, f32); 7] = { const PI_12: f64 = f64::consts::PI / 12.0; let mut ratios = [(0.0, 0.0); 7]; for (is_pos, ratio) in ratios.iter_mut().enumerate() { let is_ratio = (PI_12 * is_pos as f64).tan(); *ratio = ( (is_ratio / (1.0 + is_ratio)) as f32, (1.0 / (1.0 + is_ratio)) as f32 ); } ratios[6] = (1.0, 0.0); ratios }; } /// Decorrelates mid and side channels into left and right channels. /// /// In mid-side (MS) stereo, the left and right channels are encoded as average (mid) and /// difference (side) components. /// /// As per ISO/IEC 11172-3, to reconstruct the left and right channels, the following calculation /// is performed: /// /// ```text /// l[i] = (m[i] + s[i]) / sqrt(2) /// r[i] = (m[i] - s[i]) / sqrt(2) /// ``` /// where: /// l[i], and r[i] are the left and right channels, respectively. /// m[i], and s[i] are the mid and side channels, respectively. /// /// In the bitstream, m[i] is transmitted in channel 0, while s[i] in channel 1. After decoding, /// the left channel replaces m[i] in channel 0, and the right channel replaces s[i] in channel /// 1. fn process_mid_side(mid: &mut [f32], side: &mut [f32]) { debug_assert!(mid.len() == side.len()); for (m, s) in mid.iter_mut().zip(side) { let left = (*m + *s) * f32::consts::FRAC_1_SQRT_2; let right = (*m - *s) * f32::consts::FRAC_1_SQRT_2; *m = left; *s = right; } } /// Decodes channel 0 of the intensity stereo coded signal into left and right channels. /// /// As per ISO/IEC 11172-3, the following calculation may be performed to decode the intensity /// stereo coded signal into left and right channels. /// /// ```text /// l[i] = ch0[i] * k_l /// r[i] = ch0[i] * l_r /// ``` /// /// where: /// l[i], and r[i] are the left and right channels, respectively. /// ch0[i] is the intensity stereo coded signal found in channel 0. /// k_l, and k_r are the left and right channel ratios, respectively. fn process_intensity( intensity_pos: u8, intensity_table: &[(f32, f32)], intensity_max: u8, mid_side: bool, ch0: &mut [f32], ch1: &mut [f32], ) { if intensity_pos < intensity_max { let (ratio_l, ratio_r) = intensity_table[usize::from(intensity_pos)]; for (l, r) in ch0.iter_mut().zip(ch1) { let is = *l; *l = ratio_l * is; *r = ratio_r * is; } } else if mid_side { process_mid_side(ch0, ch1); } } /// Determines if a band is zeroed. #[inline(always)] fn is_zero_band(band: &[f32]) -> bool { !band.iter().any(|&x| x != 0.0) } /// Decodes all intensity stereo coded bands within an entire long block and returns the intensity /// bound. fn process_intensity_long_block( header: &FrameHeader, granule: &Granule, mid_side: bool, max_bound: usize, ch0: &mut [f32; 576], ch1: &mut [f32; 576], ) -> usize { // As per ISO/IEC 11172-3 and ISO/IEC 13818-3, for long blocks that have intensity stereo // coding enabled, all bands starting after the last non-zero band in channel 1 may be // intensity stereo coded. // // The scale-factors in channel 1 for those respective bands determine the intensity position. // The rzero sample index is the index of last non-zero sample plus 1. let rzero = granule.channels[1].rzero; // Select the intensity stereo ratios table. let (is_table, is_inv_pos) = if header.is_mpeg1() { (&INTENSITY_STEREO_RATIOS_MPEG1[..], INTENSITY_INV_POS_MPEG1) } else { let is_scale = granule.channels[1].scalefac_compress & 1; (&INTENSITY_STEREO_RATIOS_MPEG2[usize::from(is_scale)][..], INTENSITY_INV_POS_MPEG2) }; let bands = &SFB_LONG_BANDS[header.sample_rate_idx]; // The intensity positions are stored in the right channel (channel 1) scalefactors. The // intensity position for band 21 is not coded and is copied from band 20. let mut is_pos = [0; 22]; is_pos.copy_from_slice(&granule.channels[1].scalefacs[..22]); is_pos[21] = is_pos[20]; // Create an iterator that yields a band start-end pair, and scale-factor. let bands_iter = bands.iter().zip(&bands[1..]).zip(is_pos.iter()); let mut bound = max_bound; // Iterate over each band and decode the intensity stereo coding if the band is zero. for ((&start, &end), &is_pos) in bands_iter.rev() { // Bands starting above rzero are always 0, however bands below it are ambiguous. let is_zero_band = start >= rzero || is_zero_band(&ch1[start..end]); if is_zero_band { process_intensity( is_pos, is_table, is_inv_pos, mid_side, &mut ch0[start..end], &mut ch1[start..end], ); } else { break; } // Update the intensity bound to the start of the band since it has now been processed. bound = start; } bound } /// Decodes all intensity stereo coded bands within an entire short block and returns the intensity /// bound. fn process_intensity_short_block( header: &FrameHeader, granule: &Granule, is_mixed: bool, mid_side: bool, max_bound: usize, ch0: &mut [f32; 576], ch1: &mut [f32; 576], ) -> usize { // For short, non-mixed, blocks, each band is composed of 3 windows (windows 0 thru 2). Windows // are interleaved in each band. // // +--------------+--------------+--------------+-------+ // | sfb0 | sfb1 | sfb2 | ... | // +--------------+--------------+--------------+-------+ // | w0 | w1 | w2 | w0 | w1 | w2 | w0 | w1 | w2 | ... | // +--------------+--------------+--------------+-------+ // // However, each window of the same index is logically contiguous as depicted below. // // +------+------+------+------+ // | sfb0 | sfb1 | sfb2 | .... | // +------+------+------+------+ // | w0 | w0 | w0 | .... | // +-------------+------+------+ // | w1 | w1 | w1 | .... | // +-------------+------+------+ // | w2 | w2 | w2 | .... | // +------+------+------+------+ // // Each logically contiguous window may have it's own intensity bound. For example, in the // example below, the intensity bound for window 0 is sfb0, for window 1 it's sfb2, and for // window 2 it's sfb1. // // +------+------+------+------+ // | sfb0 | sfb1 | sfb2 | .... | // +------+------+------+------+ // w0 | 0000 | 0000 | 0000 | 0... | // +-------------+------+------+ // w1 | abcd | xyzw | 0000 | 0... | // +-------------+------+------+ // w2 | xyz0 | 0000 | 0000 | 0... | // +------+------+------+------+ // // For short blocks that are mixed, the long bands at the start follow the same rules as long // blocks (see above). For example, for the block below, if sfb1 is the intensity bound, then // all samples from sfb1 onwards must be zero. If the intensity bound is not within the long // bands then the rules stated above are followed whereby each window has it's own intensity // bound. // // |> Long bands |> Short bands (3 windows) // +------+------+------+--------+--------+------+ // | sfb0 | sfb1 | .... | sfbN-2 | sfbN-1 | sfbN | // |------+------+------+--------+--------+------+ // | | | | w0 | w0 | w0 | // | | | +--------+--------+------+ // | | | .... | w1 | w1 | w1 | // | | | +--------+--------+------+ // | | | | w2 | w2 | w2 | // +------+------+------+--------+--------+------+ // // First, if the short block is mixed, the get pair of short and long bands. Otherwise, if the // block is not mixed, get the short bands. In both cases, the index of the last scale-factor is // also returned. let (short_bands, long_bands, mut sfi) = if is_mixed { let bands = SFB_MIXED_BANDS[header.sample_rate_idx]; let switch = SFB_MIXED_SWITCH_POINT[header.sample_rate_idx]; // Variable number of short and long scalefactor bands based on the switch point. (&bands[switch..], Some(&bands[..switch + 1]), bands.len() - 1) } else { // 39 scalefactors from 13 scalefactor bands with 3 short windows per band. (&SFB_SHORT_BANDS[header.sample_rate_idx][..], None, 39) }; // Select the intensity stereo ratios table based on the bitstream version. let (is_table, is_inv_pos) = if header.is_mpeg1() { (&INTENSITY_STEREO_RATIOS_MPEG1[..], INTENSITY_INV_POS_MPEG1) } else { let is_scale = granule.channels[1].scalefac_compress & 1; (&INTENSITY_STEREO_RATIOS_MPEG2[usize::from(is_scale)][..], INTENSITY_INV_POS_MPEG2) }; // The intensity position for the final band (last three short windows) is not coded and is // copied from the previous band. let mut is_pos = [0; 39]; is_pos[..36].copy_from_slice(&granule.channels[1].scalefacs[..36]); is_pos[36..].copy_from_slice(&granule.channels[1].scalefacs[33..36]); let mut window_is_zero = [true; 3]; let mut bound = max_bound; let mut found_bound = false; // Process the short bands. for (((&s0, &s1), &s2), &s3) in short_bands .iter() .zip(&short_bands[1..]) .zip(&short_bands[2..]) .zip(&short_bands[3..]) .step_by(3) .rev() { // For each short band, the following logic is repeated for each of the three windows. // // First, if the corresponding window in the previous band was zeroed, check if the // window in this band is also zeroed. Note that if the window is non-zero, this statement // short-circuits and avoids the costly zero-check. window_is_zero[2] = window_is_zero[2] && is_zero_band(&ch1[s2..s3]); // If the window is zeroed, process it with intensity stereo. if window_is_zero[2] { process_intensity( is_pos[sfi - 1], is_table, is_inv_pos, mid_side, &mut ch0[s2..s3], &mut ch1[s2..s3], ); } else if mid_side { // If the window is non-zeroed, process it with mid-side stereo. process_mid_side(&mut ch0[s2..s3], &mut ch1[s2..s3]); } // Decrement the scalefactor (intensity position) index to advance to the next window. sfi -= 1; // Repeat the same process for the second window. window_is_zero[1] = window_is_zero[1] && is_zero_band(&ch1[s1..s2]); if window_is_zero[1] { process_intensity( is_pos[sfi - 1], is_table, is_inv_pos, mid_side, &mut ch0[s1..s2], &mut ch1[s1..s2], ); } else if mid_side { process_mid_side(&mut ch0[s1..s2], &mut ch1[s1..s2]); } sfi -= 1; // Repeat the same process for the third window. window_is_zero[0] = window_is_zero[0] && is_zero_band(&ch1[s0..s1]); if window_is_zero[0] { process_intensity( is_pos[sfi - 1], is_table, is_inv_pos, mid_side, &mut ch0[s0..s1], &mut ch1[s0..s1], ); } else if mid_side { process_mid_side(&mut ch0[s0..s1], &mut ch1[s0..s1]); } sfi -= 1; // Update the intensity bound to the start of the first window since all three windows have // now been processed by either intensity or mid-side stereo. Note that this is the "final" // intensity bound of all the windows in the short bands. Individual windows may have // reached their intensity bound earlier. Those windows are processed with mid-side stereo. bound = s0; // Determine if all windows non-zero. found_bound = !window_is_zero[0] && !window_is_zero[1] && !window_is_zero[2]; // If all windows are non-zero then the all the remaining bands should be processed with // mid-side stereo. Break out early in this case. if found_bound { break; } } // If the final intensity bound was not found within the short bands, then it may be found // within the long bands if the short block is mixed. if !found_bound { // If the short block is mixed, the long bands will not be None. if let Some(long_bands) = long_bands { // Process the long bands exactly as if it were a long block. for (&start, &end) in long_bands.iter().zip(&long_bands[1..]).rev() { let is_zero_band = is_zero_band(&ch1[start..end]); if is_zero_band { process_intensity( is_pos[sfi - 1], is_table, is_inv_pos, mid_side, &mut ch0[start..end], &mut ch1[start..end], ); } else { break; } sfi -= 1; bound = start; } } } // Return the intensity bound. bound } /// Perform joint stereo decoding on the channel pair. pub(super) fn stereo( header: &FrameHeader, granule: &mut Granule, ch: &mut [[f32; 576]; 2], ) -> Result<()> { // Determine whether mid-side, and/or intensity stereo coding is used. let (mid_side, intensity) = match header.channel_mode { ChannelMode::JointStereo(Mode::Layer3 { mid_side, intensity }) => (mid_side, intensity), ChannelMode::JointStereo(Mode::Intensity { .. }) => { // This function only supports decoding Layer 3 stereo encodings, it is a fundamental // error in the decoder logic if layer 1 or 2 stereo encodings are being decoded with // this function. panic!("invalid mode extension for layer 3 stereo decoding") } _ => return Ok(()), }; // The block types must be the same. if granule.channels[0].block_type != granule.channels[1].block_type { return decode_error("mpa: stereo channel pair block_type mismatch"); } // Split the sample buffer into two channels. let (ch0, ch1) = { let (ch0, ch1) = ch.split_first_mut().unwrap(); (ch0, &mut ch1[0]) }; // Joint stereo processing as specified in layer 3 is a combination of mid-side, and intensity // encoding schemes. Each scale-factor band may use either mid-side, intensity, or no stereo // encoding. The type of encoding used for each scale-factor band is determined by the MPEG // bitstream version, the mode extension, the block type, and the content of the scale-factor // bands. let end = max(granule.channels[0].rzero, granule.channels[1].rzero); // Decode intensity stereo coded bands if it is enabled and get the intensity bound. let is_bound = if intensity { // Decode intensity stereo coded bands based on bitstream version and block type. match granule.channels[1].block_type { BlockType::Short { is_mixed } => { process_intensity_short_block(header, granule, is_mixed, mid_side, end, ch0, ch1) } _ => process_intensity_long_block(header, granule, mid_side, end, ch0, ch1), } } // If intensity stereo coding is not enabled, then all samples are processed with mid-side // stereo decoding. In other words, there are no samples encoded with intensity stereo and // therefore the intensity bound is equal to the end of the non-zero portion of the samples. else { end }; // If mid-side stereo coding is enabled, all samples up to the intensity bound should be // decoded as mid-side stereo. if mid_side && is_bound > 0 { process_mid_side(&mut ch0[0..is_bound], &mut ch1[0..is_bound]); } // With joint stereo encoding, there is usually a mismatch between the number of samples // initially read from the bitstream for each channel. This count is stored as the rzero sample // index. However, after joint stereo decoding, both channels will have the same number of // samples. Update rzero for both channels with the actual number of samples. if intensity || mid_side { granule.channels[0].rzero = end; granule.channels[1].rzero = end; } Ok(()) } symphonia-bundle-mp3-0.5.2/src/lib.rs000075500000000000000000000027671046102023000155250ustar 00000000000000// Symphonia // Copyright (c) 2019-2022 The Project Symphonia Developers. // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. #![warn(rust_2018_idioms)] #![forbid(unsafe_code)] // The following lints are allowed in all Symphonia crates. Please see clippy.toml for their // justification. #![allow(clippy::comparison_chain)] #![allow(clippy::excessive_precision)] #![allow(clippy::identity_op)] #![allow(clippy::manual_range_contains)] // Shared modules. mod common; mod header; // Demuxer module. mod demuxer; // Decoder modules. #[cfg(any(feature = "mp1", feature = "mp2", feature = "mp3"))] mod decoder; #[cfg(any(feature = "mp1", feature = "mp2", feature = "mp3"))] mod synthesis; // Shared layer 1 & 2 decoder support module. #[cfg(any(feature = "mp1", feature = "mp2"))] mod layer12; // Layer-specific decoder support modules. #[cfg(feature = "mp1")] mod layer1; #[cfg(feature = "mp2")] mod layer2; #[cfg(feature = "mp3")] mod layer3; #[cfg(any(feature = "mp1", feature = "mp2", feature = "mp3"))] pub use decoder::MpaDecoder; pub use demuxer::MpaReader; // For SemVer compatibility in v0.5.x series. #[deprecated = "use `symphonia_bundle_mp3::MpaDecoder` instead"] #[cfg(any(feature = "mp1", feature = "mp2", feature = "mp3"))] pub type Mp3Decoder = MpaDecoder; #[deprecated = "use `symphonia_bundle_mp3::MpaReader` instead"] pub type Mp3Reader = MpaReader; symphonia-bundle-mp3-0.5.2/src/synthesis.rs000064400000000000000000001051071046102023000167750ustar 00000000000000// Symphonia // Copyright (c) 2019-2022 The Project Symphonia Developers. // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. //! The `synthesis` module implements the polyphase synthesis filterbank of the MPEG audio standard. /// Synthesis window D[i], defined in Table B.3 of ISO/IEC 11172-3. #[allow(clippy::unreadable_literal)] #[rustfmt::skip] const SYNTHESIS_D: [f32; 512] = [ 0.000000000, -0.000015259, -0.000015259, -0.000015259, -0.000015259, -0.000015259, -0.000015259, -0.000030518, -0.000030518, -0.000030518, -0.000030518, -0.000045776, -0.000045776, -0.000061035, -0.000061035, -0.000076294, -0.000076294, -0.000091553, -0.000106812, -0.000106812, -0.000122070, -0.000137329, -0.000152588, -0.000167847, -0.000198364, -0.000213623, -0.000244141, -0.000259399, -0.000289917, -0.000320435, -0.000366211, -0.000396729, -0.000442505, -0.000473022, -0.000534058, -0.000579834, -0.000625610, -0.000686646, -0.000747681, -0.000808716, -0.000885010, -0.000961304, -0.001037598, -0.001113892, -0.001205444, -0.001296997, -0.001388550, -0.001480103, -0.001586914, -0.001693726, -0.001785278, -0.001907349, -0.002014160, -0.002120972, -0.002243042, -0.002349854, -0.002456665, -0.002578735, -0.002685547, -0.002792358, -0.002899170, -0.002990723, -0.003082275, -0.003173828, 0.003250122, 0.003326416, 0.003387451, 0.003433228, 0.003463745, 0.003479004, 0.003479004, 0.003463745, 0.003417969, 0.003372192, 0.003280640, 0.003173828, 0.003051758, 0.002883911, 0.002700806, 0.002487183, 0.002227783, 0.001937866, 0.001617432, 0.001266479, 0.000869751, 0.000442505, -0.000030518, -0.000549316, -0.001098633, -0.001693726, -0.002334595, -0.003005981, -0.003723145, -0.004486084, -0.005294800, -0.006118774, -0.007003784, -0.007919312, -0.008865356, -0.009841919, -0.010848999, -0.011886597, -0.012939453, -0.014022827, -0.015121460, -0.016235352, -0.017349243, -0.018463135, -0.019577026, -0.020690918, -0.021789551, -0.022857666, -0.023910522, -0.024932861, -0.025909424, -0.026840210, -0.027725220, -0.028533936, -0.029281616, -0.029937744, -0.030532837, -0.031005859, -0.031387329, -0.031661987, -0.031814575, -0.031845093, -0.031738281, -0.031478882, 0.031082153, 0.030517578, 0.029785156, 0.028884888, 0.027801514, 0.026535034, 0.025085449, 0.023422241, 0.021575928, 0.019531250, 0.017257690, 0.014801025, 0.012115479, 0.009231567, 0.006134033, 0.002822876, -0.000686646, -0.004394531, -0.008316040, -0.012420654, -0.016708374, -0.021179199, -0.025817871, -0.030609131, -0.035552979, -0.040634155, -0.045837402, -0.051132202, -0.056533813, -0.061996460, -0.067520142, -0.073059082, -0.078628540, -0.084182739, -0.089706421, -0.095169067, -0.100540161, -0.105819702, -0.110946655, -0.115921021, -0.120697021, -0.125259399, -0.129562378, -0.133590698, -0.137298584, -0.140670776, -0.143676758, -0.146255493, -0.148422241, -0.150115967, -0.151306152, -0.151962280, -0.152069092, -0.151596069, -0.150497437, -0.148773193, -0.146362305, -0.143264771, -0.139450073, -0.134887695, -0.129577637, -0.123474121, -0.116577148, -0.108856201, 0.100311279, 0.090927124, 0.080688477, 0.069595337, 0.057617187, 0.044784546, 0.031082153, 0.016510010, 0.001068115, -0.015228271, -0.032379150, -0.050354004, -0.069168091, -0.088775635, -0.109161377, -0.130310059, -0.152206421, -0.174789429, -0.198059082, -0.221984863, -0.246505737, -0.271591187, -0.297210693, -0.323318481, -0.349868774, -0.376800537, -0.404083252, -0.431655884, -0.459472656, -0.487472534, -0.515609741, -0.543823242, -0.572036743, -0.600219727, -0.628295898, -0.656219482, -0.683914185, -0.711318970, -0.738372803, -0.765029907, -0.791213989, -0.816864014, -0.841949463, -0.866363525, -0.890090942, -0.913055420, -0.935195923, -0.956481934, -0.976852417, -0.996246338, -1.014617920, -1.031936646, -1.048156738, -1.063217163, -1.077117920, -1.089782715, -1.101211548, -1.111373901, -1.120223999, -1.127746582, -1.133926392, -1.138763428, -1.142211914, -1.144287109, 1.144989014, 1.144287109, 1.142211914, 1.138763428, 1.133926392, 1.127746582, 1.120223999, 1.111373901, 1.101211548, 1.089782715, 1.077117920, 1.063217163, 1.048156738, 1.031936646, 1.014617920, 0.996246338, 0.976852417, 0.956481934, 0.935195923, 0.913055420, 0.890090942, 0.866363525, 0.841949463, 0.816864014, 0.791213989, 0.765029907, 0.738372803, 0.711318970, 0.683914185, 0.656219482, 0.628295898, 0.600219727, 0.572036743, 0.543823242, 0.515609741, 0.487472534, 0.459472656, 0.431655884, 0.404083252, 0.376800537, 0.349868774, 0.323318481, 0.297210693, 0.271591187, 0.246505737, 0.221984863, 0.198059082, 0.174789429, 0.152206421, 0.130310059, 0.109161377, 0.088775635, 0.069168091, 0.050354004, 0.032379150, 0.015228271, -0.001068115, -0.016510010, -0.031082153, -0.044784546, -0.057617187, -0.069595337, -0.080688477, -0.090927124, 0.100311279, 0.108856201, 0.116577148, 0.123474121, 0.129577637, 0.134887695, 0.139450073, 0.143264771, 0.146362305, 0.148773193, 0.150497437, 0.151596069, 0.152069092, 0.151962280, 0.151306152, 0.150115967, 0.148422241, 0.146255493, 0.143676758, 0.140670776, 0.137298584, 0.133590698, 0.129562378, 0.125259399, 0.120697021, 0.115921021, 0.110946655, 0.105819702, 0.100540161, 0.095169067, 0.089706421, 0.084182739, 0.078628540, 0.073059082, 0.067520142, 0.061996460, 0.056533813, 0.051132202, 0.045837402, 0.040634155, 0.035552979, 0.030609131, 0.025817871, 0.021179199, 0.016708374, 0.012420654, 0.008316040, 0.004394531, 0.000686646, -0.002822876, -0.006134033, -0.009231567, -0.012115479, -0.014801025, -0.017257690, -0.019531250, -0.021575928, -0.023422241, -0.025085449, -0.026535034, -0.027801514, -0.028884888, -0.029785156, -0.030517578, 0.031082153, 0.031478882, 0.031738281, 0.031845093, 0.031814575, 0.031661987, 0.031387329, 0.031005859, 0.030532837, 0.029937744, 0.029281616, 0.028533936, 0.027725220, 0.026840210, 0.025909424, 0.024932861, 0.023910522, 0.022857666, 0.021789551, 0.020690918, 0.019577026, 0.018463135, 0.017349243, 0.016235352, 0.015121460, 0.014022827, 0.012939453, 0.011886597, 0.010848999, 0.009841919, 0.008865356, 0.007919312, 0.007003784, 0.006118774, 0.005294800, 0.004486084, 0.003723145, 0.003005981, 0.002334595, 0.001693726, 0.001098633, 0.000549316, 0.000030518, -0.000442505, -0.000869751, -0.001266479, -0.001617432, -0.001937866, -0.002227783, -0.002487183, -0.002700806, -0.002883911, -0.003051758, -0.003173828, -0.003280640, -0.003372192, -0.003417969, -0.003463745, -0.003479004, -0.003479004, -0.003463745, -0.003433228, -0.003387451, -0.003326416, 0.003250122, 0.003173828, 0.003082275, 0.002990723, 0.002899170, 0.002792358, 0.002685547, 0.002578735, 0.002456665, 0.002349854, 0.002243042, 0.002120972, 0.002014160, 0.001907349, 0.001785278, 0.001693726, 0.001586914, 0.001480103, 0.001388550, 0.001296997, 0.001205444, 0.001113892, 0.001037598, 0.000961304, 0.000885010, 0.000808716, 0.000747681, 0.000686646, 0.000625610, 0.000579834, 0.000534058, 0.000473022, 0.000442505, 0.000396729, 0.000366211, 0.000320435, 0.000289917, 0.000259399, 0.000244141, 0.000213623, 0.000198364, 0.000167847, 0.000152588, 0.000137329, 0.000122070, 0.000106812, 0.000106812, 0.000091553, 0.000076294, 0.000076294, 0.000061035, 0.000061035, 0.000045776, 0.000045776, 0.000030518, 0.000030518, 0.000030518, 0.000030518, 0.000015259, 0.000015259, 0.000015259, 0.000015259, 0.000015259, 0.000015259, ]; /// `SynthesisState` maintains the persistant state of sub-band synthesis. pub struct SynthesisState { v_vec: [[f32; 64]; 16], v_front: usize, } impl Default for SynthesisState { fn default() -> Self { SynthesisState { v_vec: [[0f32; 64]; 16], v_front: 0 } } } /// Sub-band synthesis transforms 32 sub-band blocks containing 18 time-domain samples each into /// 18 blocks of 32 PCM audio samples. pub fn synthesis(state: &mut SynthesisState, n_frames: usize, in_samples: &[f32], out: &mut [f32]) { let mut s_vec = [0f32; 32]; let mut d_vec = [0f32; 32]; assert!(in_samples.len() == 32 * n_frames); // There are 18 synthesized PCM sample blocks. for b in 0..n_frames { // First, select the b-th sample from each of the 32 sub-bands, and place them in the s // vector, s_vec. for i in 0..32 { s_vec[i] = in_samples[n_frames * i + b]; } // Get the front slot of the v_vec FIFO. let v_vec = &mut state.v_vec[state.v_front]; // Matrixing is performed next. As per the standard, matrixing would require 2048 // multiplications per sub-band! However, following the method by Konstantinides // published in [1], it is possible to achieve the same result through the use of a 32-point // DCT followed by some reconstruction. // // It should be noted that this is a deceptively simple solution. It is instructive to // derive the algorithm before getting to the implementation to better understand what is // happening, and where the edge-cases are. // // First, there are a few key observations to this approach: // // 1) The "matrixing" operation as per the standard is simply a 32-point MDCT. Note that // an N-point MDCT produces a 2N-point output. // // 2) The output of the MDCT contains repeated blocks of samples. If the result of a // MDCT defined as is X[0..64), then: // // 1) X(16.. 0] = X(48..32] // 2) X[48..64) = -X[16..32) // // Corollary: Only points [16..48) of the MDCT are actually required! All other // points are redundant. // // 3) Points [16..48) of the MDCT can be mapped from a 32-point DCT of the input // vector thus allowing the use of an efficient DCT algorithm. // // The mappings above can be found graphically by plotting each row of the cosine // coefficient matricies of both the DCT and MDCT side-by side. The mapping becomes readily // apparent, and so too do the exceptions. // // Using the observations above, if we apply a 32-point DCT transform to the input vector, // s_vec, and place the output in the DCT output vector, d_vec, we obtain the plot labelled // d_vec below. // // Next, assuming the 32-point MDCT output vector is denoted v_vec. Map the samples from the // 32-point DCT, d_vec[0..32], to points v_vec[0..16], v_vec[16..32], v_vec[32..48], and // v_vec[48..64] of the 32-point MDCT. The result is depicted graphically in the plot // labelled v_vec below. // // d_vec 0 16 32 // . . . // . +---------+ +----------+ // +-----+ A | / B | // +---------------+--------------+ // // v_vec 0 16 32 48 64 // . . . . . // . +-----------+ . . . // . / B | . . . // +---------------+--------------+--------------+---------------+ // . | -B / | -A +-----+-----+ -A | // . +----------+ +--------+ . +---------+ // // Note however that the mappings in the previous step have exceptions for boundary samples. // These exceptions can be seen when plotting the coefficient matricies as mentioned above. // The mapping for boundary samples are as follows: // // 1) v_vec[ 0] = d_vec[16] // 2) v_vec[32] = -d_vec[16] // 3) v_vec[48] = -d_vec[ 0] // 4) v_vec[16] = 0.0 // // The final algorithm written below performs the copy and flip operations of each 16 sample // quadrant in seperate loops to assist auto-vectorization. The boundary samples are // excluded from these loops and handled manually afterwards. // // [1] K. Konstantinides, "Fast subband filtering in MPEG audio coding", Signal Processing // Letters IEEE, vol. 1, no. 2, pp. 26-28, 1994. // // https://ieeexplore.ieee.org/abstract/document/300309 dct32(&s_vec, &mut d_vec); for (d, s) in v_vec[48 - 15..48 + 0].iter_mut().rev().zip(&d_vec[1..16]) { *d = -s; } for (d, s) in v_vec[48 + 1..48 + 16].iter_mut().zip(&d_vec[1..16]) { *d = -s; } for (d, s) in v_vec[16 + 1..16 + 16].iter_mut().rev().zip(&d_vec[17..32]) { *d = -s; } for (d, s) in v_vec[1..16].iter_mut().zip(&d_vec[17..32]) { *d = *s; } v_vec[0] = d_vec[16]; v_vec[32] = -d_vec[16]; v_vec[48] = -d_vec[0]; v_vec[16] = 0.0; // Next, as per the specification, build a vector, u_vec, by iterating over the 16 slots in // v_vec, and copying the first 32 samples of EVEN numbered v_vec slots, and the last 32 // samples of ODD numbered v_vec slots sequentially into u_vec. // // For example, given: // // 0 32 64 96 128 160 192 224 256 896 928 960 992 1024 // +----+----+----+----+----+----+----+----+ . . . . . . +----+-----+----+----+ // v_vec | a : b | c : d | e : f | g | h | . . . . . . | w : x | y : z | // +----+----+----+----+----+----+----+----+ . . . . . . +----+-----+----+----+ // [ Slot 0 ][ Slot 1 ][ Slot 2 ][ Slot 3 ] . . . . . . [ Slot 14 ][ Slot 15 ] // // Assuming v_front, the front of the FIFO, is slot 0, then u_vec is filled as follows: // // 0 32 64 96 128 448 480 512 // +----+----+----+----+ . . . . +----+----+ // u_vec | a | d | e | h | . . . . | w | z | // +----+----+----+----+ . . . . +----+----+ // // Finally, generate the 32 sample PCM blocks. Assuming s[i] is sample i of a PCM sample // block, the following equation governs sample generation: // // 16 // s[i] = SUM { u_vec[32*j + i] * D[32*j + i] } for i=0..32 // j=0 // // where: // D[0..512] is the synthesis window provided in table B.3 of ISO/IEC 11172-3. // // In words, u_vec is logically partitioned into 16 slots of 32 samples each (i.e., // slot 0 spans u_vec[0..32], slot 1 spans u_vec[32..64], and so on). Then, the i-th // sample in the PCM block is the summation of the i-th sample in each of the 16 u_vec // slots after being multiplied by the synthesis window. // // But wait! This is VERY inefficient! // // If PCM sample generation is reframed such that instead of iterating j for every i, i is // iterated through for every j, then it is possible to iterate straight-through // v_vec[j][0..32] and D[32*j..(32*j) + 32] while multiplying and accumulating the // intermediary calculations in a zeroed output vector, o_vec. After iterating over every j, // o_vec can be copied to the output sample buffer, out, in one block. // // Using this method, there is no reason to build u_vec and cache locality is greatly // improved. let mut o_vec = [0f32; 32]; for j in 0..8 { let v_start = state.v_front + (j << 1); let v0 = &state.v_vec[(v_start + 0) & 0xf][0..32]; let v1 = &state.v_vec[(v_start + 1) & 0xf][32..64]; let k = j << 6; for i in 0..32 { o_vec[i] += v0[i] * SYNTHESIS_D[k + i + 0]; o_vec[i] += v1[i] * SYNTHESIS_D[k + i + 32]; } } // Clamp and copy the PCM samples from o_vec to the output buffer. let offset = b << 5; for (o, s) in out[offset..offset + 32].iter_mut().zip(&o_vec) { *o = s.clamp(-1.0, 1.0); } // Shift the v_vec FIFO. The value v_front is the index of the 64 sample slot in v_vec // that will be overwritten next iteration. Conversely, that makes it the front of the // FIFO for the purpose of building u_vec. We would like to overwrite the oldest slot, // so we subtract 1 via a wrapping addition to move the front backwards by 1 slot, // effectively overwriting the oldest slot with the soon-to-be newest. state.v_front = (state.v_front + 15) & 0xf; } } /// Performs a 32-point Discrete Cosine Transform (DCT) using Byeong Gi Lee's fast algorithm /// published in article [1] without inverse square-root 2 scaling. /// /// This is a straight-forward implemention of the recursive algorithm, flattened into a single /// function body to avoid the overhead of function calls and the stack. /// /// [1] B.G. Lee, "A new algorithm to compute the discrete cosine transform", IEEE Transactions /// on Acoustics, Speech, and Signal Processing, vol. 32, no. 6, pp. 1243-1245, 1984. /// /// https://ieeexplore.ieee.org/document/1164443 fn dct32(x: &[f32; 32], y: &mut [f32; 32]) { // The following tables are pre-computed values of the the following equation: // // c[i] = 1.0 / [2.0 * cos((PI / N) * (2*i + 1))] for i = 0..N/2 // // where N = [32, 16, 8, 4, 2], for COS_16, COS8, COS_4, and COS_2, respectively. const COS_16: [f32; 16] = [ 0.500_602_998_235_196_3, // i= 0 0.505_470_959_897_543_6, // i= 1 0.515_447_309_922_624_6, // i= 2 0.531_042_591_089_784_1, // i= 3 0.553_103_896_034_444_5, // i= 4 0.582_934_968_206_133_9, // i= 5 0.622_504_123_035_664_8, // i= 6 0.674_808_341_455_005_7, // i= 7 0.744_536_271_002_298_6, // i= 8 0.839_349_645_415_526_8, // i= 9 0.972_568_237_861_960_8, // i=10 1.169_439_933_432_884_7, // i=11 1.484_164_616_314_166_2, // i=12 2.057_781_009_953_410_8, // i=13 3.407_608_418_468_719_0, // i=14 10.190_008_123_548_032_9, // i=15 ]; const COS_8: [f32; 8] = [ 0.502_419_286_188_155_7, // i=0 0.522_498_614_939_688_9, // i=1 0.566_944_034_816_357_7, // i=2 0.646_821_783_359_990_1, // i=3 0.788_154_623_451_250_2, // i=4 1.060_677_685_990_347_1, // i=5 1.722_447_098_238_334_2, // i=6 5.101_148_618_689_155_3, // i=7 ]; const COS_4: [f32; 4] = [ 0.509_795_579_104_159_2, // i=0 0.601_344_886_935_045_3, // i=1 0.899_976_223_136_415_6, // i=2 2.562_915_447_741_505_5, // i=3 ]; const COS_2: [f32; 2] = [ 0.541_196_100_146_197_0, // i=0 1.306_562_964_876_376_4, // i=1 ]; const COS_1: f32 = 0.707_106_781_186_547_5; // 16-point DCT decomposition let mut t0 = [ (x[0] + x[32 - 1]), (x[1] + x[32 - 2]), (x[2] + x[32 - 3]), (x[3] + x[32 - 4]), (x[4] + x[32 - 5]), (x[5] + x[32 - 6]), (x[6] + x[32 - 7]), (x[7] + x[32 - 8]), (x[8] + x[32 - 9]), (x[9] + x[32 - 10]), (x[10] + x[32 - 11]), (x[11] + x[32 - 12]), (x[12] + x[32 - 13]), (x[13] + x[32 - 14]), (x[14] + x[32 - 15]), (x[15] + x[32 - 16]), (x[0] - x[32 - 1]) * COS_16[0], (x[1] - x[32 - 2]) * COS_16[1], (x[2] - x[32 - 3]) * COS_16[2], (x[3] - x[32 - 4]) * COS_16[3], (x[4] - x[32 - 5]) * COS_16[4], (x[5] - x[32 - 6]) * COS_16[5], (x[6] - x[32 - 7]) * COS_16[6], (x[7] - x[32 - 8]) * COS_16[7], (x[8] - x[32 - 9]) * COS_16[8], (x[9] - x[32 - 10]) * COS_16[9], (x[10] - x[32 - 11]) * COS_16[10], (x[11] - x[32 - 12]) * COS_16[11], (x[12] - x[32 - 13]) * COS_16[12], (x[13] - x[32 - 14]) * COS_16[13], (x[14] - x[32 - 15]) * COS_16[14], (x[15] - x[32 - 16]) * COS_16[15], ]; // 16-point DCT decomposition of t0[0..16] { let mut t1 = [ (t0[0] + t0[16 - 1]), (t0[1] + t0[16 - 2]), (t0[2] + t0[16 - 3]), (t0[3] + t0[16 - 4]), (t0[4] + t0[16 - 5]), (t0[5] + t0[16 - 6]), (t0[6] + t0[16 - 7]), (t0[7] + t0[16 - 8]), (t0[0] - t0[16 - 1]) * COS_8[0], (t0[1] - t0[16 - 2]) * COS_8[1], (t0[2] - t0[16 - 3]) * COS_8[2], (t0[3] - t0[16 - 4]) * COS_8[3], (t0[4] - t0[16 - 5]) * COS_8[4], (t0[5] - t0[16 - 6]) * COS_8[5], (t0[6] - t0[16 - 7]) * COS_8[6], (t0[7] - t0[16 - 8]) * COS_8[7], ]; // 8-point DCT decomposition of t1[0..8] { let mut t2 = [ (t1[0] + t1[8 - 1]), (t1[1] + t1[8 - 2]), (t1[2] + t1[8 - 3]), (t1[3] + t1[8 - 4]), (t1[0] - t1[8 - 1]) * COS_4[0], (t1[1] - t1[8 - 2]) * COS_4[1], (t1[2] - t1[8 - 3]) * COS_4[2], (t1[3] - t1[8 - 4]) * COS_4[3], ]; // 4-point DCT decomposition of t2[0..4] { let mut t3 = [ (t2[0] + t2[4 - 1]), (t2[1] + t2[4 - 2]), (t2[0] - t2[4 - 1]) * COS_2[0], (t2[1] - t2[4 - 2]) * COS_2[1], ]; // 2-point DCT decomposition of t3[0..2] { let t4 = [(t3[0] + t3[2 - 1]), (t3[0] - t3[2 - 1]) * COS_1]; t3[0] = t4[0]; t3[1] = t4[1]; } // 2-point DCT decomposition of t3[2..4] { let t4 = [(t3[2] + t3[4 - 1]), (t3[2] - t3[4 - 1]) * COS_1]; t3[2 + 0] = t4[0]; t3[2 + 1] = t4[1]; } t2[0 + 0] = t3[0]; t2[0 + 1] = t3[2] + t3[3]; t2[0 + 2] = t3[1]; t2[0 + 3] = t3[3]; } // 4-point DCT decomposition of t2[4..8] { let mut t3 = [ (t2[4] + t2[8 - 1]), (t2[5] + t2[8 - 2]), (t2[4] - t2[8 - 1]) * COS_2[0], (t2[5] - t2[8 - 2]) * COS_2[1], ]; // 2-point DCT decomposition of t3[0..2] { let t4 = [(t3[0] + t3[2 - 1]), (t3[0] - t3[2 - 1]) * COS_1]; t3[0] = t4[0]; t3[1] = t4[1]; } // 2-point DCT decomposition of t3[2..4] { let t4 = [(t3[2] + t3[4 - 1]), (t3[2] - t3[4 - 1]) * COS_1]; t3[2 + 0] = t4[0]; t3[2 + 1] = t4[1]; } t2[4 + 0] = t3[0]; t2[4 + 1] = t3[2] + t3[3]; t2[4 + 2] = t3[1]; t2[4 + 3] = t3[3]; } // Recombine t2[0..4] and t2[4..8], overwriting t1[0..8]. for i in 0..3 { t1[(i << 1) + 0] = t2[i]; t1[(i << 1) + 1] = t2[4 + i] + t2[4 + i + 1]; } t1[8 - 2] = t2[4 - 1]; t1[8 - 1] = t2[8 - 1]; } // 8-point DCT decomposition of t1[8..16] { let mut t2 = [ (t1[8] + t1[16 - 1]), (t1[9] + t1[16 - 2]), (t1[10] + t1[16 - 3]), (t1[11] + t1[16 - 4]), (t1[8] - t1[16 - 1]) * COS_4[0], (t1[9] - t1[16 - 2]) * COS_4[1], (t1[10] - t1[16 - 3]) * COS_4[2], (t1[11] - t1[16 - 4]) * COS_4[3], ]; // 4-point DCT decomposition of t2[0..4] { let mut t3 = [ (t2[0] + t2[4 - 1]), (t2[1] + t2[4 - 2]), (t2[0] - t2[4 - 1]) * COS_2[0], (t2[1] - t2[4 - 2]) * COS_2[1], ]; // 2-point DCT decomposition of t3[0..2] { let t4 = [(t3[0] + t3[2 - 1]), (t3[0] - t3[2 - 1]) * COS_1]; t3[0] = t4[0]; t3[1] = t4[1]; } // 2-point DCT decomposition of t3[2..4] { let t4 = [(t3[2] + t3[4 - 1]), (t3[2] - t3[4 - 1]) * COS_1]; t3[2 + 0] = t4[0]; t3[2 + 1] = t4[1]; } t2[0 + 0] = t3[0]; t2[0 + 1] = t3[2] + t3[3]; t2[0 + 2] = t3[1]; t2[0 + 3] = t3[3]; } // 4-point DCT decomposition of t2[4..8] { let mut t3 = [ (t2[4] + t2[8 - 1]), (t2[5] + t2[8 - 2]), (t2[4] - t2[8 - 1]) * COS_2[0], (t2[5] - t2[8 - 2]) * COS_2[1], ]; // 2-point DCT decomposition of t3[0..2] { let t4 = [(t3[0] + t3[2 - 1]), (t3[0] - t3[2 - 1]) * COS_1]; t3[0] = t4[0]; t3[1] = t4[1]; } // 2-point DCT decomposition of t3[2..4] { let t4 = [(t3[2] + t3[4 - 1]), (t3[2] - t3[4 - 1]) * COS_1]; t3[2 + 0] = t4[0]; t3[2 + 1] = t4[1]; } t2[4 + 0] = t3[0]; t2[4 + 1] = t3[2] + t3[3]; t2[4 + 2] = t3[1]; t2[4 + 3] = t3[3]; } // Recombine t2[0..4] and t2[4..8], overwriting t1[8..16]. for i in 0..3 { t1[8 + (i << 1) + 0] = t2[i]; t1[8 + (i << 1) + 1] = t2[4 + i] + t2[4 + i + 1]; } t1[16 - 2] = t2[4 - 1]; t1[16 - 1] = t2[8 - 1]; } // Recombine t1[0..8] and t1[8..16], overwriting t0[0..16]. for i in 0..7 { t0[(i << 1) + 0] = t1[i]; t0[(i << 1) + 1] = t1[8 + i] + t1[8 + i + 1]; } t0[16 - 2] = t1[8 - 1]; t0[16 - 1] = t1[16 - 1]; } // 16-point DCT decomposition of t0[16..32] { let mut t1 = [ (t0[16] + t0[32 - 1]), (t0[17] + t0[32 - 2]), (t0[18] + t0[32 - 3]), (t0[19] + t0[32 - 4]), (t0[20] + t0[32 - 5]), (t0[21] + t0[32 - 6]), (t0[22] + t0[32 - 7]), (t0[23] + t0[32 - 8]), (t0[16] - t0[32 - 1]) * COS_8[0], (t0[17] - t0[32 - 2]) * COS_8[1], (t0[18] - t0[32 - 3]) * COS_8[2], (t0[19] - t0[32 - 4]) * COS_8[3], (t0[20] - t0[32 - 5]) * COS_8[4], (t0[21] - t0[32 - 6]) * COS_8[5], (t0[22] - t0[32 - 7]) * COS_8[6], (t0[23] - t0[32 - 8]) * COS_8[7], ]; // 8-point DCT decomposition of t1[0..8] { let mut t2 = [ (t1[0] + t1[8 - 1]), (t1[1] + t1[8 - 2]), (t1[2] + t1[8 - 3]), (t1[3] + t1[8 - 4]), (t1[0] - t1[8 - 1]) * COS_4[0], (t1[1] - t1[8 - 2]) * COS_4[1], (t1[2] - t1[8 - 3]) * COS_4[2], (t1[3] - t1[8 - 4]) * COS_4[3], ]; // 4-point DCT decomposition of t2[0..4] { let mut t3 = [ (t2[0] + t2[4 - 1]), (t2[1] + t2[4 - 2]), (t2[0] - t2[4 - 1]) * COS_2[0], (t2[1] - t2[4 - 2]) * COS_2[1], ]; // 2-point DCT decomposition of t3[0..2] { let t4 = [(t3[0] + t3[2 - 1]), (t3[0] - t3[2 - 1]) * COS_1]; t3[0] = t4[0]; t3[1] = t4[1]; } // 2-point DCT decomposition of t3[2..4] { let t4 = [(t3[2] + t3[4 - 1]), (t3[2] - t3[4 - 1]) * COS_1]; t3[2 + 0] = t4[0]; t3[2 + 1] = t4[1]; } t2[0 + 0] = t3[0]; t2[0 + 1] = t3[2] + t3[3]; t2[0 + 2] = t3[1]; t2[0 + 3] = t3[3]; } // 4-point DCT decomposition of t2[4..8] { let mut t3 = [ (t2[4] + t2[8 - 1]), (t2[5] + t2[8 - 2]), (t2[4] - t2[8 - 1]) * COS_2[0], (t2[5] - t2[8 - 2]) * COS_2[1], ]; // 2-point DCT decomposition of t3[0..2] { let t4 = [(t3[0] + t3[2 - 1]), (t3[0] - t3[2 - 1]) * COS_1]; t3[0] = t4[0]; t3[1] = t4[1]; } // 2-point DCT decomposition of t3[2..4] { let t4 = [(t3[2] + t3[4 - 1]), (t3[2] - t3[4 - 1]) * COS_1]; t3[2 + 0] = t4[0]; t3[2 + 1] = t4[1]; } t2[4 + 0] = t3[0]; t2[4 + 1] = t3[2] + t3[3]; t2[4 + 2] = t3[1]; t2[4 + 3] = t3[3]; } // Recombine t2[0..4] and t2[4..8], overwriting t1[0..8]. for i in 0..3 { t1[(i << 1) + 0] = t2[i]; t1[(i << 1) + 1] = t2[4 + i] + t2[4 + i + 1]; } t1[8 - 2] = t2[4 - 1]; t1[8 - 1] = t2[8 - 1]; } // 8-point DCT decomposition of t1[8..16] { let mut t2 = [ (t1[8] + t1[16 - 1]), (t1[9] + t1[16 - 2]), (t1[10] + t1[16 - 3]), (t1[11] + t1[16 - 4]), (t1[8] - t1[16 - 1]) * COS_4[0], (t1[9] - t1[16 - 2]) * COS_4[1], (t1[10] - t1[16 - 3]) * COS_4[2], (t1[11] - t1[16 - 4]) * COS_4[3], ]; // 4-point DCT decomposition of t2[0..4] { let mut t3 = [ (t2[0] + t2[4 - 1]), (t2[1] + t2[4 - 2]), (t2[0] - t2[4 - 1]) * COS_2[0], (t2[1] - t2[4 - 2]) * COS_2[1], ]; // 2-point DCT decomposition of t3[0..2] { let t4 = [(t3[0] + t3[2 - 1]), (t3[0] - t3[2 - 1]) * COS_1]; t3[0] = t4[0]; t3[1] = t4[1]; } // 2-point DCT decomposition of t3[2..4] { let t4 = [(t3[2] + t3[4 - 1]), (t3[2] - t3[4 - 1]) * COS_1]; t3[2 + 0] = t4[0]; t3[2 + 1] = t4[1]; } t2[0 + 0] = t3[0]; t2[0 + 1] = t3[2] + t3[3]; t2[0 + 2] = t3[1]; t2[0 + 3] = t3[3]; } // 4-point DCT decomposition of t2[4..8] { let mut t3 = [ (t2[4] + t2[8 - 1]), (t2[5] + t2[8 - 2]), (t2[4] - t2[8 - 1]) * COS_2[0], (t2[5] - t2[8 - 2]) * COS_2[1], ]; // 2-point DCT decomposition of t3[0..2] { let t4 = [(t3[0] + t3[2 - 1]), (t3[0] - t3[2 - 1]) * COS_1]; t3[0] = t4[0]; t3[1] = t4[1]; } // 2-point DCT decomposition of t3[2..4] { let t4 = [(t3[2] + t3[4 - 1]), (t3[2] - t3[4 - 1]) * COS_1]; t3[2 + 0] = t4[0]; t3[2 + 1] = t4[1]; } t2[4 + 0] = t3[0]; t2[4 + 1] = t3[2] + t3[3]; t2[4 + 2] = t3[1]; t2[4 + 3] = t3[3]; } // Recombine t2[0..4] and t2[4..8], overwriting t1[8..16]. for i in 0..3 { t1[8 + (i << 1) + 0] = t2[i]; t1[8 + (i << 1) + 1] = t2[4 + i] + t2[4 + i + 1]; } t1[16 - 2] = t2[4 - 1]; t1[16 - 1] = t2[8 - 1]; } // Recombine t1[0..8] and t1[8..16], overwriting t0[0..16]. for i in 0..7 { t0[16 + (i << 1) + 0] = t1[i]; t0[16 + (i << 1) + 1] = t1[8 + i] + t1[8 + i + 1]; } t0[32 - 2] = t1[8 - 1]; t0[32 - 1] = t1[16 - 1]; } // Recombine t1[0..16] and t1[16..32] into y. for i in 0..15 { y[(i << 1) + 0] = t0[i]; y[(i << 1) + 1] = t0[16 + i] + t0[16 + i + 1]; } y[32 - 2] = t0[16 - 1]; y[32 - 1] = t0[32 - 1]; } #[cfg(test)] mod tests { use super::dct32; use std::f64; fn dct32_analytical(x: &[f32; 32]) -> [f32; 32] { const PI_32: f64 = f64::consts::PI / 32.0; let mut result = [0f32; 32]; for (i, item) in result.iter_mut().enumerate() { *item = x .iter() .enumerate() .map(|(j, &jtem)| jtem * (PI_32 * (i as f64) * ((j as f64) + 0.5)).cos() as f32) .sum(); } result } #[test] fn verify_dct32() { const TEST_VECTOR: [f32; 32] = [ 0.1710, 0.1705, 0.3476, 0.1866, 0.4784, 0.6525, 0.2690, 0.9996, // 0.1864, 0.7277, 0.1163, 0.6620, 0.0911, 0.3225, 0.1126, 0.5344, // 0.7839, 0.9741, 0.8757, 0.5763, 0.5926, 0.2756, 0.1757, 0.6531, // 0.7101, 0.7376, 0.1924, 0.0351, 0.8044, 0.2409, 0.9347, 0.9417, // ]; let mut test_result = [0f32; 32]; dct32(&TEST_VECTOR, &mut test_result); let actual_result = dct32_analytical(&TEST_VECTOR); for i in 0..32 { assert!((actual_result[i] - test_result[i]).abs() < 0.00001); } } }