symphonia-codec-aac-0.5.4/.cargo_vcs_info.json0000644000000001610000000000100146440ustar { "git": { "sha1": "d3b7742fa73674b70d9ab80cc5f8384cc653df3a" }, "path_in_vcs": "symphonia-codec-aac" }symphonia-codec-aac-0.5.4/Cargo.toml0000644000000022470000000000100126510ustar # 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-codec-aac" version = "0.5.4" authors = [ "Philip Deljanov ", "Kostya Shishkov ", ] description = "Pure Rust AAC decoder (a part of project Symphonia)." homepage = "https://github.com/pdeljanov/Symphonia" readme = "README.md" keywords = [ "audio", "codec", "decoder", "aac", "m4a", ] categories = [ "multimedia", "multimedia::audio", "multimedia::encoding", ] license = "MPL-2.0" repository = "https://github.com/pdeljanov/Symphonia" [dependencies.lazy_static] version = "1.4.0" [dependencies.log] version = "0.4" [dependencies.symphonia-core] version = "0.5.4" symphonia-codec-aac-0.5.4/Cargo.toml.orig000064400000000000000000000012241046102023000163240ustar 00000000000000[package] name = "symphonia-codec-aac" version = "0.5.4" description = "Pure Rust AAC decoder (a part of project Symphonia)." homepage = "https://github.com/pdeljanov/Symphonia" repository = "https://github.com/pdeljanov/Symphonia" authors = ["Philip Deljanov ", "Kostya Shishkov "] license = "MPL-2.0" readme = "README.md" categories = ["multimedia", "multimedia::audio", "multimedia::encoding"] keywords = ["audio", "codec", "decoder", "aac", "m4a"] edition = "2018" rust-version = "1.53" [dependencies] log = "0.4" lazy_static = "1.4.0" symphonia-core = { version = "0.5.4", path = "../symphonia-core" }symphonia-codec-aac-0.5.4/README.md000064400000000000000000000017261046102023000147230ustar 00000000000000# Symphonia AAC Codec [![Docs](https://docs.rs/symphonia-codec-aac/badge.svg)](https://docs.rs/symphonia-codec-aac) Advanced Audio Coding (AAC) 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 the low-complexity (LC) profile as defined in ISO/IEC 14496-3. ## Attribution Symphonia's AAC decoder was ported and relicensed from the [NihAV](https://nihav.org/) project with permission from the original author, Kostya Shishkov. The first commit with the original decoder is `3aeeb22`. ## License Symphonia is provided under the MPL v2.0 license. Please refer to the LICENSE file for more details. ## Contributing Symphonia is a free and open-source project that welcomes contributions! To get started, please read our [Contribution Guidelines](https://github.com/pdeljanov/Symphonia/tree/master/CONTRIBUTING.md). symphonia-codec-aac-0.5.4/src/aac/codebooks.rs000064400000000000000000000634601046102023000173000ustar 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::*, ReadBitsLtr}; use lazy_static::lazy_static; #[rustfmt::skip] const SPECTRUM_CODEBOOK1_LENS: [u8; 81] = [ 11, 9, 11, 10, 7, 10, 11, 9, 11, 10, 7, 10, 7, 5, 7, 9, 7, 10, 11, 9, 11, 9, 7, 9, 11, 9, 11, 9, 7, 9, 7, 5, 7, 9, 7, 9, 7, 5, 7, 5, 1, 5, 7, 5, 7, 9, 7, 9, 7, 5, 7, 9, 7, 9, 11, 9, 11, 9, 7, 9, 11, 9, 11, 10, 7, 9, 7, 5, 7, 9, 7, 10, 11, 9, 11, 10, 7, 9, 11, 9, 11 ]; #[rustfmt::skip] const SPECTRUM_CODEBOOK1_CODES: [u32; 81] = [ 0x7f8, 0x1f1, 0x7fd, 0x3f5, 0x068, 0x3f0, 0x7f7, 0x1ec, 0x7f5, 0x3f1, 0x072, 0x3f4, 0x074, 0x011, 0x076, 0x1eb, 0x06c, 0x3f6, 0x7fc, 0x1e1, 0x7f1, 0x1f0, 0x061, 0x1f6, 0x7f2, 0x1ea, 0x7fb, 0x1f2, 0x069, 0x1ed, 0x077, 0x017, 0x06f, 0x1e6, 0x064, 0x1e5, 0x067, 0x015, 0x062, 0x012, 0x000, 0x014, 0x065, 0x016, 0x06d, 0x1e9, 0x063, 0x1e4, 0x06b, 0x013, 0x071, 0x1e3, 0x070, 0x1f3, 0x7fe, 0x1e7, 0x7f3, 0x1ef, 0x060, 0x1ee, 0x7f0, 0x1e2, 0x7fa, 0x3f3, 0x06a, 0x1e8, 0x075, 0x010, 0x073, 0x1f4, 0x06e, 0x3f7, 0x7f6, 0x1e0, 0x7f9, 0x3f2, 0x066, 0x1f5, 0x7ff, 0x1f7, 0x7f4 ]; #[rustfmt::skip] const SPECTRUM_CODEBOOK2_LENS: [u8; 81] = [ 9, 7, 9, 8, 6, 8, 9, 8, 9, 8, 6, 7, 6, 5, 6, 7, 6, 8, 9, 7, 8, 8, 6, 8, 9, 7, 9, 8, 6, 7, 6, 5, 6, 7, 6, 8, 6, 5, 6, 5, 3, 5, 6, 5, 6, 8, 6, 7, 6, 5, 6, 8, 6, 8, 9, 7, 9, 8, 6, 8, 8, 7, 9, 8, 6, 7, 6, 4, 6, 8, 6, 7, 9, 7, 9, 7, 6, 8, 9, 7, 9 ]; #[rustfmt::skip] const SPECTRUM_CODEBOOK2_CODES: [u32; 81] = [ 0x1f3, 0x06f, 0x1fd, 0x0eb, 0x023, 0x0ea, 0x1f7, 0x0e8, 0x1fa, 0x0f2, 0x02d, 0x070, 0x020, 0x006, 0x02b, 0x06e, 0x028, 0x0e9, 0x1f9, 0x066, 0x0f8, 0x0e7, 0x01b, 0x0f1, 0x1f4, 0x06b, 0x1f5, 0x0ec, 0x02a, 0x06c, 0x02c, 0x00a, 0x027, 0x067, 0x01a, 0x0f5, 0x024, 0x008, 0x01f, 0x009, 0x000, 0x007, 0x01d, 0x00b, 0x030, 0x0ef, 0x01c, 0x064, 0x01e, 0x00c, 0x029, 0x0f3, 0x02f, 0x0f0, 0x1fc, 0x071, 0x1f2, 0x0f4, 0x021, 0x0e6, 0x0f7, 0x068, 0x1f8, 0x0ee, 0x022, 0x065, 0x031, 0x002, 0x026, 0x0ed, 0x025, 0x06a, 0x1fb, 0x072, 0x1fe, 0x069, 0x02e, 0x0f6, 0x1ff, 0x06d, 0x1f6 ]; #[rustfmt::skip] const SPECTRUM_CODEBOOK3_LENS: [u8; 81] = [ 1, 4, 8, 4, 5, 8, 9, 9, 10, 4, 6, 9, 6, 6, 9, 9, 9, 10, 9, 10, 13, 9, 9, 11, 11, 10, 12, 4, 6, 10, 6, 7, 10, 10, 10, 12, 5, 7, 11, 6, 7, 10, 9, 9, 11, 9, 10, 13, 8, 9, 12, 10, 11, 12, 8, 10, 15, 9, 11, 15, 13, 14, 16, 8, 10, 14, 9, 10, 14, 12, 12, 15, 11, 12, 16, 10, 11, 15, 12, 12, 15 ]; #[rustfmt::skip] const SPECTRUM_CODEBOOK3_CODES: [u32; 81] = [ 0x0000, 0x0009, 0x00ef, 0x000b, 0x0019, 0x00f0, 0x01eb, 0x01e6, 0x03f2, 0x000a, 0x0035, 0x01ef, 0x0034, 0x0037, 0x01e9, 0x01ed, 0x01e7, 0x03f3, 0x01ee, 0x03ed, 0x1ffa, 0x01ec, 0x01f2, 0x07f9, 0x07f8, 0x03f8, 0x0ff8, 0x0008, 0x0038, 0x03f6, 0x0036, 0x0075, 0x03f1, 0x03eb, 0x03ec, 0x0ff4, 0x0018, 0x0076, 0x07f4, 0x0039, 0x0074, 0x03ef, 0x01f3, 0x01f4, 0x07f6, 0x01e8, 0x03ea, 0x1ffc, 0x00f2, 0x01f1, 0x0ffb, 0x03f5, 0x07f3, 0x0ffc, 0x00ee, 0x03f7, 0x7ffe, 0x01f0, 0x07f5, 0x7ffd, 0x1ffb, 0x3ffa, 0xffff, 0x00f1, 0x03f0, 0x3ffc, 0x01ea, 0x03ee, 0x3ffb, 0x0ff6, 0x0ffa, 0x7ffc, 0x07f2, 0x0ff5, 0xfffe, 0x03f4, 0x07f7, 0x7ffb, 0x0ff7, 0x0ff9, 0x7ffa ]; #[rustfmt::skip] const SPECTRUM_CODEBOOK4_LENS: [u8; 81] = [ 4, 5, 8, 5, 4, 8, 9, 8, 11, 5, 5, 8, 5, 4, 8, 8, 7, 10, 9, 8, 11, 8, 8, 10, 11, 10, 11, 4, 5, 8, 4, 4, 8, 8, 8, 10, 4, 4, 8, 4, 4, 7, 8, 7, 9, 8, 8, 10, 7, 7, 9, 10, 9, 10, 8, 8, 11, 8, 7, 10, 11, 10, 12, 8, 7, 10, 7, 7, 9, 10, 9, 11, 11, 10, 12, 10, 9, 11, 11, 10, 11 ]; #[rustfmt::skip] const SPECTRUM_CODEBOOK4_CODES: [u32; 81] = [ 0x007, 0x016, 0x0f6, 0x018, 0x008, 0x0ef, 0x1ef, 0x0f3, 0x7f8, 0x019, 0x017, 0x0ed, 0x015, 0x001, 0x0e2, 0x0f0, 0x070, 0x3f0, 0x1ee, 0x0f1, 0x7fa, 0x0ee, 0x0e4, 0x3f2, 0x7f6, 0x3ef, 0x7fd, 0x005, 0x014, 0x0f2, 0x009, 0x004, 0x0e5, 0x0f4, 0x0e8, 0x3f4, 0x006, 0x002, 0x0e7, 0x003, 0x000, 0x06b, 0x0e3, 0x069, 0x1f3, 0x0eb, 0x0e6, 0x3f6, 0x06e, 0x06a, 0x1f4, 0x3ec, 0x1f0, 0x3f9, 0x0f5, 0x0ec, 0x7fb, 0x0ea, 0x06f, 0x3f7, 0x7f9, 0x3f3, 0xfff, 0x0e9, 0x06d, 0x3f8, 0x06c, 0x068, 0x1f5, 0x3ee, 0x1f2, 0x7f4, 0x7f7, 0x3f1, 0xffe, 0x3ed, 0x1f1, 0x7f5, 0x7fe, 0x3f5, 0x7fc ]; #[rustfmt::skip] const SPECTRUM_CODEBOOK5_LENS: [u8; 81] = [ 13, 12, 11, 11, 10, 11, 11, 12, 13, 12, 11, 10, 9, 8, 9, 10, 11, 12, 12, 10, 9, 8, 7, 8, 9, 10, 11, 11, 9, 8, 5, 4, 5, 8, 9, 11, 10, 8, 7, 4, 1, 4, 7, 8, 11, 11, 9, 8, 5, 4, 5, 8, 9, 11, 11, 10, 9, 8, 7, 8, 9, 10, 11, 12, 11, 10, 9, 8, 9, 10, 11, 12, 13, 12, 12, 11, 10, 10, 11, 12, 13 ]; #[rustfmt::skip] const SPECTRUM_CODEBOOK5_CODES: [u32; 81] = [ 0x1fff, 0x0ff7, 0x07f4, 0x07e8, 0x03f1, 0x07ee, 0x07f9, 0x0ff8, 0x1ffd, 0x0ffd, 0x07f1, 0x03e8, 0x01e8, 0x00f0, 0x01ec, 0x03ee, 0x07f2, 0x0ffa, 0x0ff4, 0x03ef, 0x01f2, 0x00e8, 0x0070, 0x00ec, 0x01f0, 0x03ea, 0x07f3, 0x07eb, 0x01eb, 0x00ea, 0x001a, 0x0008, 0x0019, 0x00ee, 0x01ef, 0x07ed, 0x03f0, 0x00f2, 0x0073, 0x000b, 0x0000, 0x000a, 0x0071, 0x00f3, 0x07e9, 0x07ef, 0x01ee, 0x00ef, 0x0018, 0x0009, 0x001b, 0x00eb, 0x01e9, 0x07ec, 0x07f6, 0x03eb, 0x01f3, 0x00ed, 0x0072, 0x00e9, 0x01f1, 0x03ed, 0x07f7, 0x0ff6, 0x07f0, 0x03e9, 0x01ed, 0x00f1, 0x01ea, 0x03ec, 0x07f8, 0x0ff9, 0x1ffc, 0x0ffc, 0x0ff5, 0x07ea, 0x03f3, 0x03f2, 0x07f5, 0x0ffb, 0x1ffe ]; #[rustfmt::skip] const SPECTRUM_CODEBOOK6_LENS: [u8; 81] = [ 11, 10, 9, 9, 9, 9, 9, 10, 11, 10, 9, 8, 7, 7, 7, 8, 9, 10, 9, 8, 6, 6, 6, 6, 6, 8, 9, 9, 7, 6, 4, 4, 4, 6, 7, 9, 9, 7, 6, 4, 4, 4, 6, 7, 9, 9, 7, 6, 4, 4, 4, 6, 7, 9, 9, 8, 6, 6, 6, 6, 6, 8, 9, 10, 9, 8, 7, 7, 7, 7, 8, 10, 11, 10, 9, 9, 9, 9, 9, 10, 11 ]; #[rustfmt::skip] const SPECTRUM_CODEBOOK6_CODES: [u32; 81] = [ 0x7fe, 0x3fd, 0x1f1, 0x1eb, 0x1f4, 0x1ea, 0x1f0, 0x3fc, 0x7fd, 0x3f6, 0x1e5, 0x0ea, 0x06c, 0x071, 0x068, 0x0f0, 0x1e6, 0x3f7, 0x1f3, 0x0ef, 0x032, 0x027, 0x028, 0x026, 0x031, 0x0eb, 0x1f7, 0x1e8, 0x06f, 0x02e, 0x008, 0x004, 0x006, 0x029, 0x06b, 0x1ee, 0x1ef, 0x072, 0x02d, 0x002, 0x000, 0x003, 0x02f, 0x073, 0x1fa, 0x1e7, 0x06e, 0x02b, 0x007, 0x001, 0x005, 0x02c, 0x06d, 0x1ec, 0x1f9, 0x0ee, 0x030, 0x024, 0x02a, 0x025, 0x033, 0x0ec, 0x1f2, 0x3f8, 0x1e4, 0x0ed, 0x06a, 0x070, 0x069, 0x074, 0x0f1, 0x3fa, 0x7ff, 0x3f9, 0x1f6, 0x1ed, 0x1f8, 0x1e9, 0x1f5, 0x3fb, 0x7fc ]; #[rustfmt::skip] const SPECTRUM_CODEBOOK7_LENS: [u8; 64] = [ 1, 3, 6, 7, 8, 9, 10, 11, 3, 4, 6, 7, 8, 8, 9, 9, 6, 6, 7, 8, 8, 9, 9, 10, 7, 7, 8, 8, 9, 9, 10, 10, 8, 8, 9, 9, 10, 10, 10, 11, 9, 8, 9, 9, 10, 10, 11, 11, 10, 9, 9, 10, 10, 11, 12, 12, 11, 10, 10, 10, 11, 11, 12, 12 ]; #[rustfmt::skip] const SPECTRUM_CODEBOOK7_CODES: [u32; 64] = [ 0x000, 0x005, 0x037, 0x074, 0x0f2, 0x1eb, 0x3ed, 0x7f7, 0x004, 0x00c, 0x035, 0x071, 0x0ec, 0x0ee, 0x1ee, 0x1f5, 0x036, 0x034, 0x072, 0x0ea, 0x0f1, 0x1e9, 0x1f3, 0x3f5, 0x073, 0x070, 0x0eb, 0x0f0, 0x1f1, 0x1f0, 0x3ec, 0x3fa, 0x0f3, 0x0ed, 0x1e8, 0x1ef, 0x3ef, 0x3f1, 0x3f9, 0x7fb, 0x1ed, 0x0ef, 0x1ea, 0x1f2, 0x3f3, 0x3f8, 0x7f9, 0x7fc, 0x3ee, 0x1ec, 0x1f4, 0x3f4, 0x3f7, 0x7f8, 0xffd, 0xffe, 0x7f6, 0x3f0, 0x3f2, 0x3f6, 0x7fa, 0x7fd, 0xffc, 0xfff ]; #[rustfmt::skip] const SPECTRUM_CODEBOOK8_LENS: [u8; 64] = [ 5, 4, 5, 6, 7, 8, 9, 10, 4, 3, 4, 5, 6, 7, 7, 8, 5, 4, 4, 5, 6, 7, 7, 8, 6, 5, 5, 6, 6, 7, 8, 8, 7, 6, 6, 6, 7, 7, 8, 9, 8, 7, 6, 7, 7, 8, 8, 10, 9, 7, 7, 8, 8, 8, 9, 9, 10, 8, 8, 8, 9, 9, 9, 10 ]; #[rustfmt::skip] const SPECTRUM_CODEBOOK8_CODES: [u32; 64] = [ 0x00e, 0x005, 0x010, 0x030, 0x06f, 0x0f1, 0x1fa, 0x3fe, 0x003, 0x000, 0x004, 0x012, 0x02c, 0x06a, 0x075, 0x0f8, 0x00f, 0x002, 0x006, 0x014, 0x02e, 0x069, 0x072, 0x0f5, 0x02f, 0x011, 0x013, 0x02a, 0x032, 0x06c, 0x0ec, 0x0fa, 0x071, 0x02b, 0x02d, 0x031, 0x06d, 0x070, 0x0f2, 0x1f9, 0x0ef, 0x068, 0x033, 0x06b, 0x06e, 0x0ee, 0x0f9, 0x3fc, 0x1f8, 0x074, 0x073, 0x0ed, 0x0f0, 0x0f6, 0x1f6, 0x1fd, 0x3fd, 0x0f3, 0x0f4, 0x0f7, 0x1f7, 0x1fb, 0x1fc, 0x3ff ]; #[rustfmt::skip] const SPECTRUM_CODEBOOK9_LENS: [u8; 169] = [ 1, 3, 6, 8, 9, 10, 10, 11, 11, 12, 12, 13, 13, 3, 4, 6, 7, 8, 8, 9, 10, 10, 10, 11, 12, 12, 6, 6, 7, 8, 8, 9, 10, 10, 10, 11, 12, 12, 12, 8, 7, 8, 9, 9, 10, 10, 11, 11, 11, 12, 12, 13, 9, 8, 9, 9, 10, 10, 11, 11, 11, 12, 12, 12, 13, 10, 9, 9, 10, 11, 11, 11, 12, 11, 12, 12, 13, 13, 11, 9, 10, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 11, 10, 10, 11, 11, 12, 12, 13, 13, 13, 13, 13, 13, 11, 10, 10, 11, 11, 11, 12, 12, 13, 13, 14, 13, 14, 11, 10, 11, 11, 12, 12, 12, 12, 13, 13, 14, 14, 14, 12, 11, 11, 12, 12, 12, 13, 13, 13, 14, 14, 14, 15, 12, 11, 12, 12, 12, 13, 13, 13, 13, 14, 14, 15, 15, 13, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15 ]; #[rustfmt::skip] const SPECTRUM_CODEBOOK9_CODES: [u32; 169] = [ 0x0000, 0x0005, 0x0037, 0x00e7, 0x01de, 0x03ce, 0x03d9, 0x07c8, 0x07cd, 0x0fc8, 0x0fdd, 0x1fe4, 0x1fec, 0x0004, 0x000c, 0x0035, 0x0072, 0x00ea, 0x00ed, 0x01e2, 0x03d1, 0x03d3, 0x03e0, 0x07d8, 0x0fcf, 0x0fd5, 0x0036, 0x0034, 0x0071, 0x00e8, 0x00ec, 0x01e1, 0x03cf, 0x03dd, 0x03db, 0x07d0, 0x0fc7, 0x0fd4, 0x0fe4, 0x00e6, 0x0070, 0x00e9, 0x01dd, 0x01e3, 0x03d2, 0x03dc, 0x07cc, 0x07ca, 0x07de, 0x0fd8, 0x0fea, 0x1fdb, 0x01df, 0x00eb, 0x01dc, 0x01e6, 0x03d5, 0x03de, 0x07cb, 0x07dd, 0x07dc, 0x0fcd, 0x0fe2, 0x0fe7, 0x1fe1, 0x03d0, 0x01e0, 0x01e4, 0x03d6, 0x07c5, 0x07d1, 0x07db, 0x0fd2, 0x07e0, 0x0fd9, 0x0feb, 0x1fe3, 0x1fe9, 0x07c4, 0x01e5, 0x03d7, 0x07c6, 0x07cf, 0x07da, 0x0fcb, 0x0fda, 0x0fe3, 0x0fe9, 0x1fe6, 0x1ff3, 0x1ff7, 0x07d3, 0x03d8, 0x03e1, 0x07d4, 0x07d9, 0x0fd3, 0x0fde, 0x1fdd, 0x1fd9, 0x1fe2, 0x1fea, 0x1ff1, 0x1ff6, 0x07d2, 0x03d4, 0x03da, 0x07c7, 0x07d7, 0x07e2, 0x0fce, 0x0fdb, 0x1fd8, 0x1fee, 0x3ff0, 0x1ff4, 0x3ff2, 0x07e1, 0x03df, 0x07c9, 0x07d6, 0x0fca, 0x0fd0, 0x0fe5, 0x0fe6, 0x1feb, 0x1fef, 0x3ff3, 0x3ff4, 0x3ff5, 0x0fe0, 0x07ce, 0x07d5, 0x0fc6, 0x0fd1, 0x0fe1, 0x1fe0, 0x1fe8, 0x1ff0, 0x3ff1, 0x3ff8, 0x3ff6, 0x7ffc, 0x0fe8, 0x07df, 0x0fc9, 0x0fd7, 0x0fdc, 0x1fdc, 0x1fdf, 0x1fed, 0x1ff5, 0x3ff9, 0x3ffb, 0x7ffd, 0x7ffe, 0x1fe7, 0x0fcc, 0x0fd6, 0x0fdf, 0x1fde, 0x1fda, 0x1fe5, 0x1ff2, 0x3ffa, 0x3ff7, 0x3ffc, 0x3ffd, 0x7fff ]; #[rustfmt::skip] const SPECTRUM_CODEBOOK10_LENS: [u8; 169] = [ 6, 5, 6, 6, 7, 8, 9, 10, 10, 10, 11, 11, 12, 5, 4, 4, 5, 6, 7, 7, 8, 8, 9, 10, 10, 11, 6, 4, 5, 5, 6, 6, 7, 8, 8, 9, 9, 10, 10, 6, 5, 5, 5, 6, 7, 7, 8, 8, 9, 9, 10, 10, 7, 6, 6, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 8, 7, 6, 7, 7, 7, 8, 8, 8, 9, 10, 10, 11, 9, 7, 7, 7, 7, 8, 8, 9, 9, 9, 10, 10, 11, 9, 8, 8, 8, 8, 8, 9, 9, 9, 10, 10, 11, 11, 9, 8, 8, 8, 8, 8, 9, 9, 10, 10, 10, 11, 11, 10, 9, 9, 9, 9, 9, 9, 10, 10, 10, 11, 11, 12, 10, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 12, 11, 10, 9, 10, 10, 10, 10, 10, 11, 11, 11, 11, 12, 11, 10, 10, 10, 10, 10, 10, 11, 11, 12, 12, 12, 12 ]; #[rustfmt::skip] const SPECTRUM_CODEBOOK10_CODES: [u32; 169] = [ 0x022, 0x008, 0x01d, 0x026, 0x05f, 0x0d3, 0x1cf, 0x3d0, 0x3d7, 0x3ed, 0x7f0, 0x7f6, 0xffd, 0x007, 0x000, 0x001, 0x009, 0x020, 0x054, 0x060, 0x0d5, 0x0dc, 0x1d4, 0x3cd, 0x3de, 0x7e7, 0x01c, 0x002, 0x006, 0x00c, 0x01e, 0x028, 0x05b, 0x0cd, 0x0d9, 0x1ce, 0x1dc, 0x3d9, 0x3f1, 0x025, 0x00b, 0x00a, 0x00d, 0x024, 0x057, 0x061, 0x0cc, 0x0dd, 0x1cc, 0x1de, 0x3d3, 0x3e7, 0x05d, 0x021, 0x01f, 0x023, 0x027, 0x059, 0x064, 0x0d8, 0x0df, 0x1d2, 0x1e2, 0x3dd, 0x3ee, 0x0d1, 0x055, 0x029, 0x056, 0x058, 0x062, 0x0ce, 0x0e0, 0x0e2, 0x1da, 0x3d4, 0x3e3, 0x7eb, 0x1c9, 0x05e, 0x05a, 0x05c, 0x063, 0x0ca, 0x0da, 0x1c7, 0x1ca, 0x1e0, 0x3db, 0x3e8, 0x7ec, 0x1e3, 0x0d2, 0x0cb, 0x0d0, 0x0d7, 0x0db, 0x1c6, 0x1d5, 0x1d8, 0x3ca, 0x3da, 0x7ea, 0x7f1, 0x1e1, 0x0d4, 0x0cf, 0x0d6, 0x0de, 0x0e1, 0x1d0, 0x1d6, 0x3d1, 0x3d5, 0x3f2, 0x7ee, 0x7fb, 0x3e9, 0x1cd, 0x1c8, 0x1cb, 0x1d1, 0x1d7, 0x1df, 0x3cf, 0x3e0, 0x3ef, 0x7e6, 0x7f8, 0xffa, 0x3eb, 0x1dd, 0x1d3, 0x1d9, 0x1db, 0x3d2, 0x3cc, 0x3dc, 0x3ea, 0x7ed, 0x7f3, 0x7f9, 0xff9, 0x7f2, 0x3ce, 0x1e4, 0x3cb, 0x3d8, 0x3d6, 0x3e2, 0x3e5, 0x7e8, 0x7f4, 0x7f5, 0x7f7, 0xffb, 0x7fa, 0x3ec, 0x3df, 0x3e1, 0x3e4, 0x3e6, 0x3f0, 0x7e9, 0x7ef, 0xff8, 0xffe, 0xffc, 0xfff ]; #[rustfmt::skip] const SPECTRUM_CODEBOOK11_LENS: [u8; 289] = [ 4, 5, 6, 7, 8, 8, 9, 10, 10, 10, 11, 11, 12, 11, 12, 12, 10, 5, 4, 5, 6, 7, 7, 8, 8, 9, 9, 9, 10, 10, 10, 10, 11, 8, 6, 5, 5, 6, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 10, 8, 7, 6, 6, 6, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 10, 8, 8, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 10, 10, 10, 10, 8, 8, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 8, 9, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 10, 10, 10, 10, 10, 8, 9, 8, 8, 8, 8, 8, 8, 9, 9, 9, 10, 10, 10, 10, 10, 10, 8, 10, 9, 8, 8, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 11, 8, 10, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 11, 11, 8, 11, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 10, 11, 11, 8, 11, 10, 9, 9, 10, 9, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 8, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 9, 11, 10, 9, 9, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 9, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 9, 12, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 12, 12, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 5 ]; #[rustfmt::skip] const SPECTRUM_CODEBOOK11_CODES: [u32; 289] = [ 0x000, 0x006, 0x019, 0x03d, 0x09c, 0x0c6, 0x1a7, 0x390, 0x3c2, 0x3df, 0x7e6, 0x7f3, 0xffb, 0x7ec, 0xffa, 0xffe, 0x38e, 0x005, 0x001, 0x008, 0x014, 0x037, 0x042, 0x092, 0x0af, 0x191, 0x1a5, 0x1b5, 0x39e, 0x3c0, 0x3a2, 0x3cd, 0x7d6, 0x0ae, 0x017, 0x007, 0x009, 0x018, 0x039, 0x040, 0x08e, 0x0a3, 0x0b8, 0x199, 0x1ac, 0x1c1, 0x3b1, 0x396, 0x3be, 0x3ca, 0x09d, 0x03c, 0x015, 0x016, 0x01a, 0x03b, 0x044, 0x091, 0x0a5, 0x0be, 0x196, 0x1ae, 0x1b9, 0x3a1, 0x391, 0x3a5, 0x3d5, 0x094, 0x09a, 0x036, 0x038, 0x03a, 0x041, 0x08c, 0x09b, 0x0b0, 0x0c3, 0x19e, 0x1ab, 0x1bc, 0x39f, 0x38f, 0x3a9, 0x3cf, 0x093, 0x0bf, 0x03e, 0x03f, 0x043, 0x045, 0x09e, 0x0a7, 0x0b9, 0x194, 0x1a2, 0x1ba, 0x1c3, 0x3a6, 0x3a7, 0x3bb, 0x3d4, 0x09f, 0x1a0, 0x08f, 0x08d, 0x090, 0x098, 0x0a6, 0x0b6, 0x0c4, 0x19f, 0x1af, 0x1bf, 0x399, 0x3bf, 0x3b4, 0x3c9, 0x3e7, 0x0a8, 0x1b6, 0x0ab, 0x0a4, 0x0aa, 0x0b2, 0x0c2, 0x0c5, 0x198, 0x1a4, 0x1b8, 0x38c, 0x3a4, 0x3c4, 0x3c6, 0x3dd, 0x3e8, 0x0ad, 0x3af, 0x192, 0x0bd, 0x0bc, 0x18e, 0x197, 0x19a, 0x1a3, 0x1b1, 0x38d, 0x398, 0x3b7, 0x3d3, 0x3d1, 0x3db, 0x7dd, 0x0b4, 0x3de, 0x1a9, 0x19b, 0x19c, 0x1a1, 0x1aa, 0x1ad, 0x1b3, 0x38b, 0x3b2, 0x3b8, 0x3ce, 0x3e1, 0x3e0, 0x7d2, 0x7e5, 0x0b7, 0x7e3, 0x1bb, 0x1a8, 0x1a6, 0x1b0, 0x1b2, 0x1b7, 0x39b, 0x39a, 0x3ba, 0x3b5, 0x3d6, 0x7d7, 0x3e4, 0x7d8, 0x7ea, 0x0ba, 0x7e8, 0x3a0, 0x1bd, 0x1b4, 0x38a, 0x1c4, 0x392, 0x3aa, 0x3b0, 0x3bc, 0x3d7, 0x7d4, 0x7dc, 0x7db, 0x7d5, 0x7f0, 0x0c1, 0x7fb, 0x3c8, 0x3a3, 0x395, 0x39d, 0x3ac, 0x3ae, 0x3c5, 0x3d8, 0x3e2, 0x3e6, 0x7e4, 0x7e7, 0x7e0, 0x7e9, 0x7f7, 0x190, 0x7f2, 0x393, 0x1be, 0x1c0, 0x394, 0x397, 0x3ad, 0x3c3, 0x3c1, 0x3d2, 0x7da, 0x7d9, 0x7df, 0x7eb, 0x7f4, 0x7fa, 0x195, 0x7f8, 0x3bd, 0x39c, 0x3ab, 0x3a8, 0x3b3, 0x3b9, 0x3d0, 0x3e3, 0x3e5, 0x7e2, 0x7de, 0x7ed, 0x7f1, 0x7f9, 0x7fc, 0x193, 0xffd, 0x3dc, 0x3b6, 0x3c7, 0x3cc, 0x3cb, 0x3d9, 0x3da, 0x7d3, 0x7e1, 0x7ee, 0x7ef, 0x7f5, 0x7f6, 0xffc, 0xfff, 0x19d, 0x1c2, 0x0b5, 0x0a1, 0x096, 0x097, 0x095, 0x099, 0x0a0, 0x0a2, 0x0ac, 0x0a9, 0x0b1, 0x0b3, 0x0bb, 0x0c0, 0x18f, 0x004 ]; #[rustfmt::skip] const SCF_CODEBOOK_LENS: [u8; 121] = [ 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 18, 19, 18, 17, 17, 16, 17, 16, 16, 16, 16, 15, 15, 14, 14, 14, 14, 14, 14, 13, 13, 12, 12, 12, 11, 12, 11, 10, 10, 10, 9, 9, 8, 8, 8, 7, 6, 6, 5, 4, 3, 1, 4, 4, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 10, 11, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 16, 15, 16, 15, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19 ]; #[rustfmt::skip] const SCF_CODEBOOK_CODES: [u32; 121] = [ 0x3FFE8, 0x3FFE6, 0x3FFE7, 0x3FFE5, 0x7FFF5, 0x7FFF1, 0x7FFED, 0x7FFF6, 0x7FFEE, 0x7FFEF, 0x7FFF0, 0x7FFFC, 0x7FFFD, 0x7FFFF, 0x7FFFE, 0x7FFF7, 0x7FFF8, 0x7FFFB, 0x7FFF9, 0x3FFE4, 0x7FFFA, 0x3FFE3, 0x1FFEF, 0x1FFF0, 0x0FFF5, 0x1FFEE, 0x0FFF2, 0x0FFF3, 0x0FFF4, 0x0FFF1, 0x07FF6, 0x07FF7, 0x03FF9, 0x03FF5, 0x03FF7, 0x03FF3, 0x03FF6, 0x03FF2, 0x01FF7, 0x01FF5, 0x00FF9, 0x00FF7, 0x00FF6, 0x007F9, 0x00FF4, 0x007F8, 0x003F9, 0x003F7, 0x003F5, 0x001F8, 0x001F7, 0x000FA, 0x000F8, 0x000F6, 0x00079, 0x0003A, 0x00038, 0x0001A, 0x0000B, 0x00004, 0x00000, 0x0000A, 0x0000C, 0x0001B, 0x00039, 0x0003B, 0x00078, 0x0007A, 0x000F7, 0x000F9, 0x001F6, 0x001F9, 0x003F4, 0x003F6, 0x003F8, 0x007F5, 0x007F4, 0x007F6, 0x007F7, 0x00FF5, 0x00FF8, 0x01FF4, 0x01FF6, 0x01FF8, 0x03FF8, 0x03FF4, 0x0FFF0, 0x07FF4, 0x0FFF6, 0x07FF5, 0x3FFE2, 0x7FFD9, 0x7FFDA, 0x7FFDB, 0x7FFDC, 0x7FFDD, 0x7FFDE, 0x7FFD8, 0x7FFD2, 0x7FFD3, 0x7FFD4, 0x7FFD5, 0x7FFD6, 0x7FFF2, 0x7FFDF, 0x7FFE7, 0x7FFE8, 0x7FFE9, 0x7FFEA, 0x7FFEB, 0x7FFE6, 0x7FFE0, 0x7FFE1, 0x7FFE2, 0x7FFE3, 0x7FFE4, 0x7FFE5, 0x7FFD7, 0x7FFEC, 0x7FFF4, 0x7FFF3 ]; const AAC_QUADS: [(u8, u8, u8, u8); 81] = [ (0, 0, 0, 0), (0, 0, 0, 1), (0, 0, 0, 2), (0, 0, 1, 0), (0, 0, 1, 1), (0, 0, 1, 2), (0, 0, 2, 0), (0, 0, 2, 1), (0, 0, 2, 2), (0, 1, 0, 0), (0, 1, 0, 1), (0, 1, 0, 2), (0, 1, 1, 0), (0, 1, 1, 1), (0, 1, 1, 2), (0, 1, 2, 0), (0, 1, 2, 1), (0, 1, 2, 2), (0, 2, 0, 0), (0, 2, 0, 1), (0, 2, 0, 2), (0, 2, 1, 0), (0, 2, 1, 1), (0, 2, 1, 2), (0, 2, 2, 0), (0, 2, 2, 1), (0, 2, 2, 2), (1, 0, 0, 0), (1, 0, 0, 1), (1, 0, 0, 2), (1, 0, 1, 0), (1, 0, 1, 1), (1, 0, 1, 2), (1, 0, 2, 0), (1, 0, 2, 1), (1, 0, 2, 2), (1, 1, 0, 0), (1, 1, 0, 1), (1, 1, 0, 2), (1, 1, 1, 0), (1, 1, 1, 1), (1, 1, 1, 2), (1, 1, 2, 0), (1, 1, 2, 1), (1, 1, 2, 2), (1, 2, 0, 0), (1, 2, 0, 1), (1, 2, 0, 2), (1, 2, 1, 0), (1, 2, 1, 1), (1, 2, 1, 2), (1, 2, 2, 0), (1, 2, 2, 1), (1, 2, 2, 2), (2, 0, 0, 0), (2, 0, 0, 1), (2, 0, 0, 2), (2, 0, 1, 0), (2, 0, 1, 1), (2, 0, 1, 2), (2, 0, 2, 0), (2, 0, 2, 1), (2, 0, 2, 2), (2, 1, 0, 0), (2, 1, 0, 1), (2, 1, 0, 2), (2, 1, 1, 0), (2, 1, 1, 1), (2, 1, 1, 2), (2, 1, 2, 0), (2, 1, 2, 1), (2, 1, 2, 2), (2, 2, 0, 0), (2, 2, 0, 1), (2, 2, 0, 2), (2, 2, 1, 0), (2, 2, 1, 1), (2, 2, 1, 2), (2, 2, 2, 0), (2, 2, 2, 1), (2, 2, 2, 2), ]; struct VlcTable { codes: &'static [u32], lens: &'static [u8], } const SPECTRUM_TABLES: [VlcTable; 11] = [ VlcTable { codes: &SPECTRUM_CODEBOOK1_CODES, lens: &SPECTRUM_CODEBOOK1_LENS }, VlcTable { codes: &SPECTRUM_CODEBOOK2_CODES, lens: &SPECTRUM_CODEBOOK2_LENS }, VlcTable { codes: &SPECTRUM_CODEBOOK3_CODES, lens: &SPECTRUM_CODEBOOK3_LENS }, VlcTable { codes: &SPECTRUM_CODEBOOK4_CODES, lens: &SPECTRUM_CODEBOOK4_LENS }, VlcTable { codes: &SPECTRUM_CODEBOOK5_CODES, lens: &SPECTRUM_CODEBOOK5_LENS }, VlcTable { codes: &SPECTRUM_CODEBOOK6_CODES, lens: &SPECTRUM_CODEBOOK6_LENS }, VlcTable { codes: &SPECTRUM_CODEBOOK7_CODES, lens: &SPECTRUM_CODEBOOK7_LENS }, VlcTable { codes: &SPECTRUM_CODEBOOK8_CODES, lens: &SPECTRUM_CODEBOOK8_LENS }, VlcTable { codes: &SPECTRUM_CODEBOOK9_CODES, lens: &SPECTRUM_CODEBOOK9_LENS }, VlcTable { codes: &SPECTRUM_CODEBOOK10_CODES, lens: &SPECTRUM_CODEBOOK10_LENS }, VlcTable { codes: &SPECTRUM_CODEBOOK11_CODES, lens: &SPECTRUM_CODEBOOK11_LENS }, ]; /// Make a codebook that returns the index of the read code. trait MakeBasicCodebook { type ValueType; fn new(codebook: Codebook) -> Self; } /// Make a codebook that returns a value. trait MakeValueCodebook { type ValueType; fn new(codebook: Codebook, values: Box<[Self::ValueType]>) -> Self; } /// Codebook for spectral quads. #[derive(Default)] pub struct QuadsCodebook { codebook: Codebook, } impl QuadsCodebook { #[inline(always)] pub fn read_quant(&self, bs: &mut B) -> std::io::Result<(u8, u8, u8, u8)> { bs.read_codebook(&self.codebook).map(|(cw, _)| AAC_QUADS[cw as usize]) } } impl MakeBasicCodebook for QuadsCodebook { type ValueType = (u8, u8, u8, u8); fn new(codebook: Codebook) -> Self { Self { codebook } } } /// Codebook for spectral pairs. #[derive(Default)] pub struct PairsCodebook { codebook: Codebook, values: Box<[(f32, f32)]>, } impl PairsCodebook { #[inline(always)] pub fn read_dequant(&self, bs: &mut B) -> std::io::Result<(f32, f32)> { bs.read_codebook(&self.codebook).map(|(cw, _)| self.values[cw as usize]) } } impl MakeValueCodebook for PairsCodebook { type ValueType = (f32, f32); fn new(codebook: Codebook, values: Box<[Self::ValueType]>) -> Self { Self { codebook, values } } } /// Codebook for spectral pairs with an escape code. pub struct EscapeCodebook { codebook: Codebook, values: Box<[(u16, u16)]>, } impl EscapeCodebook { #[inline(always)] pub fn read_quant(&self, bs: &mut B) -> std::io::Result<(u16, u16)> { bs.read_codebook(&self.codebook).map(|(cw, _)| self.values[cw as usize]) } } impl MakeValueCodebook for EscapeCodebook { type ValueType = (u16, u16); fn new(codebook: Codebook, values: Box<[Self::ValueType]>) -> Self { Self { codebook, values } } } /// Given an AAC table containing a list of variable length codes and the length of each code, /// generate a codebook. fn make_raw_codebook(table: &VlcTable) -> Codebook { assert_eq!(table.codes.len(), table.lens.len()); let len = table.codes.len() as u16; // Generate the indicies for each code. let indicies: Vec = (0..len).collect(); // Generate the codebook. let mut builder = CodebookBuilder::new(BitOrder::Verbatim); // Read in 8-bit blocks. builder.bits_per_read(8); builder.make(table.codes, table.lens, &indicies).unwrap() } /// Generate a codebook, but also generate a list of values for each variable length code using /// the function `f`. The function `f` maps the index of a code to a value. fn make_value_codebook(table: &VlcTable, f: F) -> C where C: MakeValueCodebook, F: Fn(usize) -> C::ValueType, { let codebook = make_raw_codebook(table); // Generate values for the codebook. let values: Vec = (0..table.codes.len()).map(f).collect(); C::new(codebook, values.into_boxed_slice()) } /// Generate a codebook without any stored values. fn make_basic_codebook(table: &VlcTable) -> C where C: MakeBasicCodebook, { C::new(make_raw_codebook(table)) } /// Inverse quantization. #[inline(always)] fn iquant(val: usize) -> f32 { f32::powf(val as f32, 4.0 / 3.0) } fn signed_pair(cw: usize) -> (f32, f32) { let modulo_2 = MOD >> 1; let a = cw / MOD; let b = cw % MOD; let x = if modulo_2 > a { -iquant(modulo_2 - a) } else { iquant(a - modulo_2) }; let y = if modulo_2 > b { -iquant(modulo_2 - b) } else { iquant(b - modulo_2) }; (x, y) } fn unsigned_pair(cw: usize) -> (f32, f32) { (iquant(cw / MOD), iquant(cw % MOD)) } fn escape_pair(cw: usize) -> (u16, u16) { ((cw / MOD) as u16, (cw % MOD) as u16) } lazy_static! { pub static ref QUADS: [QuadsCodebook; 4] = [ make_basic_codebook(&SPECTRUM_TABLES[0]), make_basic_codebook(&SPECTRUM_TABLES[1]), make_basic_codebook(&SPECTRUM_TABLES[2]), make_basic_codebook(&SPECTRUM_TABLES[3]), ]; } lazy_static! { pub static ref PAIRS: [PairsCodebook; 6] = [ make_value_codebook(&SPECTRUM_TABLES[4], signed_pair::<9>), make_value_codebook(&SPECTRUM_TABLES[5], signed_pair::<9>), make_value_codebook(&SPECTRUM_TABLES[6], unsigned_pair::<8>), make_value_codebook(&SPECTRUM_TABLES[7], unsigned_pair::<8>), make_value_codebook(&SPECTRUM_TABLES[8], unsigned_pair::<13>), make_value_codebook(&SPECTRUM_TABLES[9], unsigned_pair::<13>), ]; } lazy_static! { pub static ref ESC: EscapeCodebook = make_value_codebook(&SPECTRUM_TABLES[10], escape_pair::<17>); } lazy_static! { pub static ref SCALEFACTORS: Codebook = { assert_eq!(SCF_CODEBOOK_CODES.len(), SCF_CODEBOOK_LENS.len()); let len = SCF_CODEBOOK_CODES.len() as u8; // Generate the values for the codebook. let values: Vec = (0..len).collect(); // Generate the codebook. let mut builder = CodebookBuilder::new(BitOrder::Verbatim); // Read in 8-bit blocks. builder.bits_per_read(8); builder.make(&SCF_CODEBOOK_CODES, &SCF_CODEBOOK_LENS, &values).unwrap() }; } symphonia-codec-aac-0.5.4/src/aac/common.rs000064400000000000000000000144041046102023000166120ustar 00000000000000// Symphonia // Copyright (c) 2019-2022 The Project Symphonia Developers. // // Previous Author: Kostya Shishkov // // This source file includes code originally written for the NihAV // project. With the author's permission, it has been relicensed for, // and ported to the Symphonia project. // // 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/. pub const MAX_WINDOWS: usize = 8; pub const MAX_SFBS: usize = 64; pub const ONLY_LONG_SEQUENCE: u8 = 0; pub const LONG_START_SEQUENCE: u8 = 1; pub const EIGHT_SHORT_SEQUENCE: u8 = 2; pub const LONG_STOP_SEQUENCE: u8 = 3; pub const SWB_OFFSET_48K_LONG: [usize; 49 + 1] = [ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 48, 56, 64, 72, 80, 88, 96, 108, 120, 132, 144, 160, 176, 196, 216, 240, 264, 292, 320, 352, 384, 416, 448, 480, 512, 544, 576, 608, 640, 672, 704, 736, 768, 800, 832, 864, 896, 928, 1024, ]; pub const SWB_OFFSET_48K_SHORT: [usize; 14 + 1] = [0, 4, 8, 12, 16, 20, 28, 36, 44, 56, 68, 80, 96, 112, 128]; pub const SWB_OFFSET_32K_LONG: [usize; 51 + 1] = [ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 48, 56, 64, 72, 80, 88, 96, 108, 120, 132, 144, 160, 176, 196, 216, 240, 264, 292, 320, 352, 384, 416, 448, 480, 512, 544, 576, 608, 640, 672, 704, 736, 768, 800, 832, 864, 896, 928, 960, 992, 1024, ]; pub const SWB_OFFSET_8K_LONG: [usize; 40 + 1] = [ 0, 12, 24, 36, 48, 60, 72, 84, 96, 108, 120, 132, 144, 156, 172, 188, 204, 220, 236, 252, 268, 288, 308, 328, 348, 372, 396, 420, 448, 476, 508, 544, 580, 620, 664, 712, 764, 820, 880, 944, 1024, ]; pub const SWB_OFFSET_8K_SHORT: [usize; 15 + 1] = [0, 4, 8, 12, 16, 20, 24, 28, 36, 44, 52, 60, 72, 88, 108, 128]; pub const SWB_OFFSET_16K_LONG: [usize; 43 + 1] = [ 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 100, 112, 124, 136, 148, 160, 172, 184, 196, 212, 228, 244, 260, 280, 300, 320, 344, 368, 396, 424, 456, 492, 532, 572, 616, 664, 716, 772, 832, 896, 960, 1024, ]; pub const SWB_OFFSET_16K_SHORT: [usize; 15 + 1] = [0, 4, 8, 12, 16, 20, 24, 28, 32, 40, 48, 60, 72, 88, 108, 128]; pub const SWB_OFFSET_24K_LONG: [usize; 47 + 1] = [ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 52, 60, 68, 76, 84, 92, 100, 108, 116, 124, 136, 148, 160, 172, 188, 204, 220, 240, 260, 284, 308, 336, 364, 396, 432, 468, 508, 552, 600, 652, 704, 768, 832, 896, 960, 1024, ]; pub const SWB_OFFSET_24K_SHORT: [usize; 15 + 1] = [0, 4, 8, 12, 16, 20, 24, 28, 36, 44, 52, 64, 76, 92, 108, 128]; pub const SWB_OFFSET_64K_LONG: [usize; 47 + 1] = [ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 64, 72, 80, 88, 100, 112, 124, 140, 156, 172, 192, 216, 240, 268, 304, 344, 384, 424, 464, 504, 544, 584, 624, 664, 704, 744, 784, 824, 864, 904, 944, 984, 1024, ]; pub const SWB_OFFSET_64K_SHORT: [usize; 12 + 1] = [0, 4, 8, 12, 16, 20, 24, 32, 40, 48, 64, 92, 128]; pub const SWB_OFFSET_96K_LONG: [usize; 41 + 1] = [ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 64, 72, 80, 88, 96, 108, 120, 132, 144, 156, 172, 188, 212, 240, 276, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960, 1024, ]; /// A Linear Congruential Generator (LCG) pseudo-random number generator from Numerical Recipes. #[derive(Clone)] pub struct Lcg { state: u32, } impl Lcg { pub fn new(state: u32) -> Self { Lcg { state } } #[inline(always)] pub fn next(&mut self) -> i32 { // Numerical Recipes LCG parameters. self.state = self.state.wrapping_mul(1664525).wrapping_add(1013904223); self.state as i32 } } #[derive(Clone, Copy)] pub struct GASubbandInfo { pub min_srate: u32, pub long_bands: &'static [usize], pub short_bands: &'static [usize], } impl GASubbandInfo { pub fn find(srate: u32) -> GASubbandInfo { for sbi in AAC_SUBBAND_INFO.iter() { if srate >= sbi.min_srate { return *sbi; } } unreachable!() } pub fn find_idx(srate: u32) -> usize { for (i, sbi) in AAC_SUBBAND_INFO.iter().enumerate() { if srate >= sbi.min_srate { return i; } } unreachable!() } } const AAC_SUBBAND_INFO: [GASubbandInfo; 12] = [ GASubbandInfo { min_srate: 92017, long_bands: &SWB_OFFSET_96K_LONG, short_bands: &SWB_OFFSET_64K_SHORT, }, //96K GASubbandInfo { min_srate: 75132, long_bands: &SWB_OFFSET_96K_LONG, short_bands: &SWB_OFFSET_64K_SHORT, }, //88.2K GASubbandInfo { min_srate: 55426, long_bands: &SWB_OFFSET_64K_LONG, short_bands: &SWB_OFFSET_64K_SHORT, }, //64K GASubbandInfo { min_srate: 46009, long_bands: &SWB_OFFSET_48K_LONG, short_bands: &SWB_OFFSET_48K_SHORT, }, //48K GASubbandInfo { min_srate: 37566, long_bands: &SWB_OFFSET_48K_LONG, short_bands: &SWB_OFFSET_48K_SHORT, }, //44.1K GASubbandInfo { min_srate: 27713, long_bands: &SWB_OFFSET_32K_LONG, short_bands: &SWB_OFFSET_48K_SHORT, }, //32K GASubbandInfo { min_srate: 23004, long_bands: &SWB_OFFSET_24K_LONG, short_bands: &SWB_OFFSET_24K_SHORT, }, //24K GASubbandInfo { min_srate: 18783, long_bands: &SWB_OFFSET_24K_LONG, short_bands: &SWB_OFFSET_24K_SHORT, }, //22.05K GASubbandInfo { min_srate: 13856, long_bands: &SWB_OFFSET_16K_LONG, short_bands: &SWB_OFFSET_16K_SHORT, }, //16K GASubbandInfo { min_srate: 11502, long_bands: &SWB_OFFSET_16K_LONG, short_bands: &SWB_OFFSET_16K_SHORT, }, //12K GASubbandInfo { min_srate: 9391, long_bands: &SWB_OFFSET_16K_LONG, short_bands: &SWB_OFFSET_16K_SHORT, }, //11.025K GASubbandInfo { min_srate: 0, long_bands: &SWB_OFFSET_8K_LONG, short_bands: &SWB_OFFSET_8K_SHORT, }, //8K ]; macro_rules! validate { ($a:expr) => { if !$a { log::error!("check failed at {}:{}", file!(), line!()); return symphonia_core::errors::decode_error("aac: invalid data"); } }; } pub(crate) use validate; symphonia-codec-aac-0.5.4/src/aac/cpe.rs000064400000000000000000000133631046102023000160740ustar 00000000000000// Symphonia // Copyright (c) 2019-2022 The Project Symphonia Developers. // // Previous Author: Kostya Shishkov // // This source file includes code originally written for the NihAV // project. With the author's permission, it has been relicensed for, // and ported to the Symphonia project. // // 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::ReadBitsLtr; use crate::aac::common::*; use crate::aac::dsp; use crate::aac::ics; use crate::common::M4AType; #[derive(Clone)] pub struct ChannelPair { pub is_pair: bool, pub channel: usize, ms_mask_present: u8, ms_used: [[bool; MAX_SFBS]; MAX_WINDOWS], ics0: ics::Ics, ics1: ics::Ics, lcg: Lcg, } impl ChannelPair { pub fn new(is_pair: bool, channel: usize, sbinfo: GASubbandInfo) -> Self { Self { is_pair, channel, ms_mask_present: 0, ms_used: [[false; MAX_SFBS]; MAX_WINDOWS], ics0: ics::Ics::new(sbinfo), ics1: ics::Ics::new(sbinfo), lcg: Lcg::new(0x1f2e3d4c), // Use the same seed as ffmpeg for symphonia-check. } } pub fn reset(&mut self) { self.ics0.reset(); self.ics1.reset(); } pub fn decode_ga_sce(&mut self, bs: &mut B, m4atype: M4AType) -> Result<()> { self.ics0.decode(bs, &mut self.lcg, m4atype, false)?; Ok(()) } pub fn decode_ga_cpe(&mut self, bs: &mut B, m4atype: M4AType) -> Result<()> { let common_window = bs.read_bool()?; if common_window { // Decode the common ICS info block into the first channel. self.ics0.info.decode(bs)?; // Mid-side stereo mask decoding. self.ms_mask_present = bs.read_bits_leq32(2)? as u8; match self.ms_mask_present { 0 | 2 => { // If mid-side mask present is 0, then mid-side coding is never used. If the // value is 2, then mid-side coding is always used. let is_used = self.ms_mask_present == 2; for g in 0..self.ics0.info.window_groups { for sfb in 0..self.ics0.info.max_sfb { self.ms_used[g][sfb] = is_used; } } } 1 => { // If mid-side mask present is 1, then read a bit for each band indicating if // the band uses mid-side coding. for g in 0..self.ics0.info.window_groups { for sfb in 0..self.ics0.info.max_sfb { self.ms_used[g][sfb] = bs.read_bool()?; } } } 3 => return decode_error("aac: invalid mid-side mask"), _ => unreachable!(), } // Copy the common ICS info decoded in the first channel to the second channel. self.ics1.info.copy_from_common(&self.ics0.info); } self.ics0.decode(bs, &mut self.lcg, m4atype, common_window)?; self.ics1.decode(bs, &mut self.lcg, m4atype, common_window)?; // Joint-stereo decoding if common_window { let bands = self.ics0.get_bands(); let mut g = 0; for w in 0..self.ics0.info.num_windows { if w > 0 && !self.ics0.info.scale_factor_grouping[w - 1] { g += 1; } for sfb in 0..self.ics0.info.max_sfb { let start = w * 128 + bands[sfb]; let end = w * 128 + bands[sfb + 1]; if self.ics1.is_intensity(g, sfb) { // Intensity stereo // Section 4.6.8.2.3 let invert = self.ms_mask_present == 1 && self.ms_used[g][sfb]; let dir = if self.ics1.get_intensity_dir(g, sfb) { 1.0 } else { -1.0 }; let factor = if invert { -1.0 } else { 1.0 }; let scale = dir * factor * self.ics1.scales[g][sfb]; let left = &self.ics0.coeffs[start..end]; let right = &mut self.ics1.coeffs[start..end]; for (l, r) in left.iter().zip(right) { *r = scale * l; } } else if self.ics0.is_noise(g, sfb) || self.ics1.is_noise(g, sfb) { // Perceptual noise substitution, do not do joint-stereo decoding. // Section 4.6.13.3 } else if self.ms_used[g][sfb] { // Mid-side stereo. let mid = &mut self.ics0.coeffs[start..end]; let side = &mut self.ics1.coeffs[start..end]; for (m, s) in mid.iter_mut().zip(side) { let tmp = *m - *s; *m += *s; *s = tmp; } } } } } Ok(()) } pub fn synth_audio( &mut self, dsp: &mut dsp::Dsp, abuf: &mut AudioBuffer, rate_idx: usize, ) { self.ics0.synth_channel(dsp, rate_idx, abuf.chan_mut(self.channel)); if self.is_pair { self.ics1.synth_channel(dsp, rate_idx, abuf.chan_mut(self.channel + 1)); } } } symphonia-codec-aac-0.5.4/src/aac/dsp.rs000064400000000000000000000130201046102023000161010ustar 00000000000000// Symphonia // Copyright (c) 2019-2022 The Project Symphonia Developers. // // Previous Author: Kostya Shishkov // // This source file includes code originally written for the NihAV // project. With the author's permission, it has been relicensed for, // and ported to the Symphonia project. // // 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::dsp::mdct::Imdct; use crate::aac::common::*; use crate::aac::window::*; const SHORT_WIN_POINT0: usize = 512 - 64; const SHORT_WIN_POINT1: usize = 512 + 64; pub struct Dsp { kbd_long_win: [f32; 1024], kbd_short_win: [f32; 128], sine_long_win: [f32; 1024], sine_short_win: [f32; 128], imdct_long: Imdct, imdct_short: Imdct, pcm_long: [f32; 2048], pcm_short: [f32; 1152], } impl Dsp { pub fn new() -> Self { let mut kbd_long_win: [f32; 1024] = [0.0; 1024]; let mut kbd_short_win: [f32; 128] = [0.0; 128]; generate_window(WindowType::KaiserBessel(4.0), 1.0, 1024, true, &mut kbd_long_win); generate_window(WindowType::KaiserBessel(6.0), 1.0, 128, true, &mut kbd_short_win); let mut sine_long_win: [f32; 1024] = [0.0; 1024]; let mut sine_short_win: [f32; 128] = [0.0; 128]; generate_window(WindowType::Sine, 1.0, 1024, true, &mut sine_long_win); generate_window(WindowType::Sine, 1.0, 128, true, &mut sine_short_win); Self { kbd_long_win, kbd_short_win, sine_long_win, sine_short_win, imdct_long: Imdct::new_scaled(1024, 1.0 / 2048.0), imdct_short: Imdct::new_scaled(128, 1.0 / 256.0), pcm_long: [0.0; 2048], pcm_short: [0.0; 1152], } } #[allow(clippy::cognitive_complexity)] pub fn synth( &mut self, coeffs: &[f32; 1024], delay: &mut [f32; 1024], seq: u8, window_shape: bool, prev_window_shape: bool, dst: &mut [f32], ) { let (long_win, short_win) = match window_shape { true => (&self.kbd_long_win, &self.kbd_short_win), false => (&self.sine_long_win, &self.sine_short_win), }; let (prev_long_win, prev_short_win) = match prev_window_shape { true => (&self.kbd_long_win, &self.kbd_short_win), false => (&self.sine_long_win, &self.sine_short_win), }; // Inverse MDCT if seq != EIGHT_SHORT_SEQUENCE { self.imdct_long.imdct(coeffs, &mut self.pcm_long); } else { for (ain, aout) in coeffs.chunks_exact(128).zip(self.pcm_long.chunks_exact_mut(256)) { self.imdct_short.imdct(ain, aout); } // Zero the eight short sequence buffer. self.pcm_short.fill(0.0); for (w, src) in self.pcm_long.chunks_exact(256).enumerate() { if w > 0 { for i in 0..128 { self.pcm_short[w * 128 + i] += src[i] * short_win[i]; self.pcm_short[w * 128 + i + 128] += src[i + 128] * short_win[127 - i]; } } else { for i in 0..128 { self.pcm_short[i] = src[i] * prev_short_win[i]; self.pcm_short[i + 128] = src[i + 128] * short_win[127 - i]; } } } } // Output new audio samples. match seq { ONLY_LONG_SEQUENCE | LONG_START_SEQUENCE => { for i in 0..1024 { dst[i] = delay[i] + (self.pcm_long[i] * prev_long_win[i]); } } EIGHT_SHORT_SEQUENCE => { dst[..SHORT_WIN_POINT0].copy_from_slice(&delay[..SHORT_WIN_POINT0]); for i in SHORT_WIN_POINT0..1024 { dst[i] = delay[i] + self.pcm_short[i - SHORT_WIN_POINT0]; } } LONG_STOP_SEQUENCE => { dst[..SHORT_WIN_POINT0].copy_from_slice(&delay[..SHORT_WIN_POINT0]); for i in SHORT_WIN_POINT0..SHORT_WIN_POINT1 { dst[i] = delay[i] + self.pcm_long[i] * prev_short_win[i - SHORT_WIN_POINT0]; } for i in SHORT_WIN_POINT1..1024 { dst[i] = delay[i] + self.pcm_long[i]; } } _ => unreachable!(), }; // Save delay for overlap. match seq { ONLY_LONG_SEQUENCE | LONG_STOP_SEQUENCE => { for i in 0..1024 { delay[i] = self.pcm_long[i + 1024] * long_win[1023 - i]; } } EIGHT_SHORT_SEQUENCE => { for i in 0..SHORT_WIN_POINT1 { // Last part is already windowed. delay[i] = self.pcm_short[i + 512 + 64]; } delay[SHORT_WIN_POINT1..].fill(0.0); } LONG_START_SEQUENCE => { delay[..SHORT_WIN_POINT0] .copy_from_slice(&self.pcm_long[1024..(SHORT_WIN_POINT0 + 1024)]); for i in SHORT_WIN_POINT0..SHORT_WIN_POINT1 { delay[i] = self.pcm_long[i + 1024] * short_win[127 - (i - SHORT_WIN_POINT0)]; } delay[SHORT_WIN_POINT1..].fill(0.0); } _ => unreachable!(), }; } } symphonia-codec-aac-0.5.4/src/aac/ics/gain.rs000064400000000000000000000022751046102023000170210ustar 00000000000000// Symphonia // Copyright (c) 2019-2022 The Project Symphonia Developers. // // Previous Author: Kostya Shishkov // // This source file includes code originally written for the NihAV // project. With the author's permission, it has been relicensed for, // and ported to the Symphonia project. // // 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::{unsupported_error, Result}; use symphonia_core::io::ReadBitsLtr; #[derive(Clone, Copy)] #[allow(dead_code)] pub struct GainControl { max_band: u8, } impl GainControl { pub fn read(bs: &mut B) -> Result> { let gain_control_data_present = bs.read_bool()?; if !gain_control_data_present { return Ok(None); } /* self.max_band = bs.read_bits_leq32(2)? as u8; if window_sequence == ONLY_LONG_SEQUENCE { for bd in 0..max_band ... } Ok(Some(Self { })) */ unsupported_error("aac: gain control data") } } symphonia-codec-aac-0.5.4/src/aac/ics/ltp.rs000064400000000000000000000033241046102023000166760ustar 00000000000000// Symphonia // Copyright (c) 2019-2022 The Project Symphonia Developers. // // Previous Author: Kostya Shishkov // // This source file includes code originally written for the NihAV // project. With the author's permission, it has been relicensed for, // and ported to the Symphonia project. // // 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::{unsupported_error, Result}; use symphonia_core::io::ReadBitsLtr; #[derive(Clone, Copy)] pub struct LtpData {} impl LtpData { pub fn read(bs: &mut B) -> Result> { let predictor_data_present = bs.read_bool()?; if !predictor_data_present { return Ok(None); } /* if is_main { let predictor_reset = bs.read_bit()?; if predictor_reset { let predictor_reset_group_number = bs.read_bits_leq32(5)?; } for sfb in 0..max_sfb.min(PRED_SFB_MAX) { prediction_used[sfb] = bs.read_bit()?; } } else { let ltp_data_present = bs.read_bit()?; if ltp_data_present { //ltp data } if common_window { let ltp_data_present = bs.read_bit()?; if ltp_data_present { //ltp data } } } Ok(Some(Self { })) */ unsupported_error("aac: predictor data") } } symphonia-codec-aac-0.5.4/src/aac/ics/mod.rs000064400000000000000000000442571046102023000166700ustar 00000000000000// Symphonia // Copyright (c) 2019-2022 The Project Symphonia Developers. // // Previous Author: Kostya Shishkov // // This source file includes code originally written for the NihAV // project. With the author's permission, it has been relicensed for, // and ported to the Symphonia project. // // 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::vlc::{Codebook, Entry8x16}; use symphonia_core::io::ReadBitsLtr; use crate::aac::codebooks; use crate::aac::common::*; use crate::aac::dsp; use crate::common::M4AType; use lazy_static::lazy_static; use log::debug; mod gain; mod ltp; mod pulse; mod tns; const ZERO_HCB: u8 = 0; const RESERVED_HCB: u8 = 12; const NOISE_HCB: u8 = 13; const INTENSITY_HCB2: u8 = 14; const INTENSITY_HCB: u8 = 15; const INTENSITY_SCALE_MIN: i16 = -155; const NORMAL_SCALE_MIN: i16 = -100; lazy_static! { /// Pre-computed table of y = x^(4/3). static ref POW43_TABLE: [f32; 8192] = { let mut pow43 = [0f32; 8192]; for (i, pow43) in pow43.iter_mut().enumerate() { *pow43 = f32::powf(i as f32, 4.0 / 3.0); } pow43 }; } lazy_static! { /// Pre-computed table of y = 2^(0.25 * (x - 156)) for decoding scale factors for normal bands. /// This table is indexed relative to -100, the minimum encoded scale factor value for normal /// bands. Therefore, an input of 0 corresponds to -100. static ref NORMAL_SCF_TABLE: [f32; 256] = { let mut table = [0f32; 256]; for (i, table) in table.iter_mut().enumerate() { *table = 2.0f32.powf(0.25 * f32::from(i as i16 - 56 + NORMAL_SCALE_MIN)) } table }; } lazy_static! { /// Pre-computed table of y = 0.5^(0.25 * (x - 155)) for decoding scale factors for intensity /// coded bands. This table is indexed relative to -155, the minimum encoded scale factor value /// for intensity coded bands. Therefore, an input of 0 corresponds to -155. static ref INTENSITY_SCF_TABLE: [f32; 256] = { let mut table = [0f32; 256]; for (i, table) in table.iter_mut().enumerate() { *table = 0.5f32.powf(0.25 * f32::from(i as i16 + INTENSITY_SCALE_MIN)); } table }; } #[derive(Clone)] pub struct IcsInfo { pub window_sequence: u8, pub prev_window_sequence: u8, pub window_shape: bool, pub prev_window_shape: bool, pub scale_factor_grouping: [bool; MAX_WINDOWS], pub group_start: [usize; MAX_WINDOWS], pub window_groups: usize, pub num_windows: usize, pub max_sfb: usize, pub long_win: bool, pub ltp: Option, } impl IcsInfo { fn new() -> Self { Self { window_sequence: 0, prev_window_sequence: 0, window_shape: false, prev_window_shape: false, scale_factor_grouping: [false; MAX_WINDOWS], group_start: [0; MAX_WINDOWS], num_windows: 0, window_groups: 0, max_sfb: 0, ltp: None, long_win: true, } } pub fn decode(&mut self, bs: &mut B) -> Result<()> { self.prev_window_sequence = self.window_sequence; self.prev_window_shape = self.window_shape; if bs.read_bool()? { return decode_error("aac: ics reserved bit set"); } self.window_sequence = bs.read_bits_leq32(2)? as u8; match self.prev_window_sequence { ONLY_LONG_SEQUENCE | LONG_STOP_SEQUENCE => { if (self.window_sequence != ONLY_LONG_SEQUENCE) && (self.window_sequence != LONG_START_SEQUENCE) { debug!("previous window is invalid"); } } LONG_START_SEQUENCE | EIGHT_SHORT_SEQUENCE => { if (self.window_sequence != EIGHT_SHORT_SEQUENCE) && (self.window_sequence != LONG_STOP_SEQUENCE) { debug!("previous window is invalid"); } } _ => {} }; self.window_shape = bs.read_bool()?; self.window_groups = 1; if self.window_sequence == EIGHT_SHORT_SEQUENCE { self.long_win = false; self.num_windows = 8; self.max_sfb = bs.read_bits_leq32(4)? as usize; for i in 0..MAX_WINDOWS - 1 { self.scale_factor_grouping[i] = bs.read_bool()?; if !self.scale_factor_grouping[i] { self.group_start[self.window_groups] = i + 1; self.window_groups += 1; } } } else { self.long_win = true; self.num_windows = 1; self.max_sfb = bs.read_bits_leq32(6)? as usize; self.ltp = ltp::LtpData::read(bs)?; } Ok(()) } pub fn copy_from_common(&mut self, other: &IcsInfo) { // Maintain the previous window sequence and shape. let prev_window_sequence = self.window_sequence; let prev_window_shape = self.window_shape; *self = other.clone(); self.prev_window_sequence = prev_window_sequence; self.prev_window_shape = prev_window_shape; } fn get_group_start(&self, g: usize) -> usize { if g == 0 { 0 } else if g >= self.window_groups { if self.long_win { 1 } else { 8 } } else { self.group_start[g] } } } #[derive(Clone)] pub struct Ics { global_gain: u8, pub info: IcsInfo, pulse: Option, tns: Option, gain: Option, sect_cb: [[u8; MAX_SFBS]; MAX_WINDOWS], sect_len: [[usize; MAX_SFBS]; MAX_WINDOWS], sfb_cb: [[u8; MAX_SFBS]; MAX_WINDOWS], num_sec: [usize; MAX_WINDOWS], pub scales: [[f32; MAX_SFBS]; MAX_WINDOWS], sbinfo: GASubbandInfo, pub coeffs: [f32; 1024], delay: [f32; 1024], } impl Ics { pub fn new(sbinfo: GASubbandInfo) -> Self { Self { global_gain: 0, info: IcsInfo::new(), pulse: None, tns: None, gain: None, sect_cb: [[0; MAX_SFBS]; MAX_WINDOWS], sect_len: [[0; MAX_SFBS]; MAX_WINDOWS], sfb_cb: [[0; MAX_SFBS]; MAX_WINDOWS], scales: [[0.0; MAX_SFBS]; MAX_WINDOWS], num_sec: [0; MAX_WINDOWS], sbinfo, coeffs: [0.0; 1024], delay: [0.0; 1024], } } pub fn reset(&mut self) { self.info = IcsInfo::new(); self.delay = [0.0; 1024]; } fn decode_section_data(&mut self, bs: &mut B) -> Result<()> { let sect_bits = if self.info.long_win { 5 } else { 3 }; let sect_esc_val = (1 << sect_bits) - 1; for g in 0..self.info.window_groups { let mut k = 0; let mut l = 0; while k < self.info.max_sfb { self.sect_cb[g][l] = bs.read_bits_leq32(4)? as u8; self.sect_len[g][l] = 0; if self.sect_cb[g][l] == RESERVED_HCB { return decode_error("aac: invalid band type"); } loop { let sect_len_incr = bs.read_bits_leq32(sect_bits)? as usize; self.sect_len[g][l] += sect_len_incr; if sect_len_incr < sect_esc_val { break; } } validate!(k + self.sect_len[g][l] <= self.info.max_sfb); for sfb in k..k + self.sect_len[g][l] { self.sfb_cb[g][sfb] = self.sect_cb[g][l]; } k += self.sect_len[g][l]; l += 1; } self.num_sec[g] = l; } Ok(()) } #[inline(always)] pub fn is_zero(&self, g: usize, sfb: usize) -> bool { self.sfb_cb[g][sfb] == ZERO_HCB } #[inline(always)] pub fn is_intensity(&self, g: usize, sfb: usize) -> bool { (self.sfb_cb[g][sfb] == INTENSITY_HCB) || (self.sfb_cb[g][sfb] == INTENSITY_HCB2) } #[inline(always)] pub fn is_noise(&self, g: usize, sfb: usize) -> bool { self.sfb_cb[g][sfb] == NOISE_HCB } #[inline(always)] pub fn get_intensity_dir(&self, g: usize, sfb: usize) -> bool { self.sfb_cb[g][sfb] == INTENSITY_HCB } fn decode_scale_factor_data(&mut self, bs: &mut B) -> Result<()> { let mut noise_pcm_flag = true; let mut scf_intensity = -INTENSITY_SCALE_MIN; let mut scf_noise = i16::from(self.global_gain) - 90 - NORMAL_SCALE_MIN; let mut scf_normal = i16::from(self.global_gain); let scf_cb: &Codebook = &codebooks::SCALEFACTORS; let table_normal_scf: &[f32; 256] = &NORMAL_SCF_TABLE; let table_intensity_scf: &[f32; 256] = &INTENSITY_SCF_TABLE; for g in 0..self.info.window_groups { for sfb in 0..self.info.max_sfb { self.scales[g][sfb] = if self.is_zero(g, sfb) { 0.0 } else if self.is_intensity(g, sfb) { scf_intensity += i16::from(bs.read_codebook(scf_cb)?.0) - 60; // Valid range is -155 to 100. Value offset by 155 for lookup table indexing. validate!((scf_intensity >= 0) && (scf_intensity < 256)); table_intensity_scf[scf_intensity as usize] } else if self.is_noise(g, sfb) { if noise_pcm_flag { noise_pcm_flag = false; scf_noise += (bs.read_bits_leq32(9)? as i16) - 256; } else { scf_noise += i16::from(bs.read_codebook(scf_cb)?.0) - 60; } // Valid range is -100 to 155. Value offset by 100 for lookup table indexing. validate!((scf_noise >= 0) && (scf_noise < 256)); table_normal_scf[scf_noise as usize] } else { scf_normal += i16::from(bs.read_codebook(scf_cb)?.0) - 60; // Valid range is -100 to 155. Value offset by 100 for lookup table indexing. validate!((scf_normal >= 0) && (scf_normal < 256)); table_normal_scf[scf_normal as usize] } } } Ok(()) } pub fn get_bands(&self) -> &'static [usize] { if self.info.long_win { self.sbinfo.long_bands } else { self.sbinfo.short_bands } } fn decode_spectrum(&mut self, bs: &mut B, lcg: &mut Lcg) -> Result<()> { // Zero all spectral coefficients. self.coeffs.fill(0.0); let bands = self.get_bands(); for g in 0..self.info.window_groups { let cur_w = self.info.get_group_start(g); let next_w = self.info.get_group_start(g + 1); for sfb in 0..self.info.max_sfb { let start = bands[sfb]; let end = bands[sfb + 1]; let cb_idx = self.sfb_cb[g][sfb]; let scale = self.scales[g][sfb]; for w in cur_w..next_w { let dst = &mut self.coeffs[start + w * 128..end + w * 128]; // Derived from ISO/IEC-14496-3 Table 4.151. match cb_idx { ZERO_HCB => (), RESERVED_HCB => (), NOISE_HCB => decode_noise(lcg, scale, dst), INTENSITY_HCB2 => (), INTENSITY_HCB => (), 1 => decode_quads_signed(bs, &codebooks::QUADS[0], scale, dst)?, 2 => decode_quads_signed(bs, &codebooks::QUADS[1], scale, dst)?, 3 => decode_quads_unsigned(bs, &codebooks::QUADS[2], scale, dst)?, 4 => decode_quads_unsigned(bs, &codebooks::QUADS[3], scale, dst)?, 5 => decode_pairs_signed(bs, &codebooks::PAIRS[0], scale, dst)?, 6 => decode_pairs_signed(bs, &codebooks::PAIRS[1], scale, dst)?, 7 => decode_pairs_unsigned(bs, &codebooks::PAIRS[2], scale, dst)?, 8 => decode_pairs_unsigned(bs, &codebooks::PAIRS[3], scale, dst)?, 9 => decode_pairs_unsigned(bs, &codebooks::PAIRS[4], scale, dst)?, 10 => decode_pairs_unsigned(bs, &codebooks::PAIRS[5], scale, dst)?, 11 => decode_pairs_unsigned_escape(bs, &codebooks::ESC, scale, dst)?, _ => unreachable!(), } } } } Ok(()) } pub fn decode( &mut self, bs: &mut B, lcg: &mut Lcg, m4atype: M4AType, common_window: bool, ) -> Result<()> { self.global_gain = bs.read_bits_leq32(8)? as u8; // If a common window is used, a common ICS info was decoded previously. if !common_window { self.info.decode(bs)?; } self.decode_section_data(bs)?; self.decode_scale_factor_data(bs)?; self.pulse = pulse::Pulse::read(bs)?; validate!(self.pulse.is_none() || self.info.long_win); let is_aac_lc = m4atype == M4AType::Lc; self.tns = tns::Tns::read(bs, &self.info, is_aac_lc)?; match m4atype { M4AType::Ssr => self.gain = gain::GainControl::read(bs)?, _ => { let gain_control_data_present = bs.read_bool()?; validate!(!gain_control_data_present); } } self.decode_spectrum(bs, lcg)?; Ok(()) } pub fn synth_channel(&mut self, dsp: &mut dsp::Dsp, rate_idx: usize, dst: &mut [f32]) { let bands = self.get_bands(); if let Some(pulse) = &self.pulse { pulse.synth(bands, &self.scales, &mut self.coeffs); } if let Some(tns) = &self.tns { tns.synth(&self.info, bands, rate_idx, &mut self.coeffs); } dsp.synth( &self.coeffs, &mut self.delay, self.info.window_sequence, self.info.window_shape, self.info.prev_window_shape, dst, ); } } /// Perceptual noise substitution decode step. Section 4.6.13.3. fn decode_noise(lcg: &mut Lcg, sf: f32, dst: &mut [f32]) { let mut energy = 0.0; for spec in dst.iter_mut() { // The random number generator outputs i32, but the largest signed // integer that can convert to f32 is i16. *spec = f32::from((lcg.next() >> 16) as i16); energy += *spec * *spec; } let scale = sf / energy.sqrt(); for spec in dst.iter_mut() { *spec *= scale; } } #[inline(always)] fn decode_sign(val: u32) -> f32 { 1.0 - 2.0 * val as f32 } fn decode_quads_unsigned( bs: &mut B, cb: &codebooks::QuadsCodebook, scale: f32, dst: &mut [f32], ) -> Result<()> { // Table of dequantized samples for all possible quantized values. let iquant = [0.0, scale, 2.51984209978974632953 * scale]; for out in dst.chunks_exact_mut(4) { let (a, b, c, d) = cb.read_quant(bs)?; if a != 0 { out[0] = decode_sign(bs.read_bit()?) * iquant[a as usize]; } if b != 0 { out[1] = decode_sign(bs.read_bit()?) * iquant[b as usize]; } if c != 0 { out[2] = decode_sign(bs.read_bit()?) * iquant[c as usize]; } if d != 0 { out[3] = decode_sign(bs.read_bit()?) * iquant[d as usize]; } } Ok(()) } fn decode_quads_signed( bs: &mut B, cb: &codebooks::QuadsCodebook, scale: f32, dst: &mut [f32], ) -> Result<()> { // Table of dequantized samples for all possible quantized values. let iquant = [-scale, 0.0, scale]; for out in dst.chunks_exact_mut(4) { let (a, b, c, d) = cb.read_quant(bs)?; out[0] = iquant[a as usize]; out[1] = iquant[b as usize]; out[2] = iquant[c as usize]; out[3] = iquant[d as usize]; } Ok(()) } fn decode_pairs_signed( bs: &mut B, cb: &codebooks::PairsCodebook, scale: f32, dst: &mut [f32], ) -> Result<()> { for out in dst.chunks_exact_mut(2) { let (x, y) = cb.read_dequant(bs)?; out[0] = x * scale; out[1] = y * scale; } Ok(()) } fn decode_pairs_unsigned( bs: &mut B, cb: &codebooks::PairsCodebook, scale: f32, dst: &mut [f32], ) -> Result<()> { for out in dst.chunks_exact_mut(2) { let (x, y) = cb.read_dequant(bs)?; let sign_x = if x != 0.0 { decode_sign(bs.read_bit()?) } else { 1.0 }; let sign_y = if y != 0.0 { decode_sign(bs.read_bit()?) } else { 1.0 }; out[0] = sign_x * x * scale; out[1] = sign_y * y * scale; } Ok(()) } fn decode_pairs_unsigned_escape( bs: &mut B, cb: &codebooks::EscapeCodebook, scale: f32, dst: &mut [f32], ) -> Result<()> { let iquant: &[f32; 8192] = &POW43_TABLE; for out in dst.chunks_exact_mut(2) { let (a, b) = cb.read_quant(bs)?; // Read the signs of the dequantized samples. let sign_x = if a != 0 { decode_sign(bs.read_bit()?) } else { 1.0 }; let sign_y = if b != 0 { decode_sign(bs.read_bit()?) } else { 1.0 }; let x = iquant[if a == 16 { read_escape(bs)? } else { a } as usize]; let y = iquant[if b == 16 { read_escape(bs)? } else { b } as usize]; out[0] = sign_x * x * scale; out[1] = sign_y * y * scale; } Ok(()) } fn read_escape(bs: &mut B) -> Result { let n = bs.read_unary_ones()?; validate!(n < 9); // The escape word is added to 2^(n + 4) to yield the unsigned value. let word = (1 << (n + 4)) + bs.read_bits_leq32(n + 4)? as u16; Ok(word) } symphonia-codec-aac-0.5.4/src/aac/ics/pulse.rs000064400000000000000000000055211046102023000172300ustar 00000000000000// Symphonia // Copyright (c) 2019-2022 The Project Symphonia Developers. // // Previous Author: Kostya Shishkov // // This source file includes code originally written for the NihAV // project. With the author's permission, it has been relicensed for, // and ported to the Symphonia project. // // 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::aac::common::{MAX_SFBS, MAX_WINDOWS}; #[inline(always)] fn iquant(val: f32) -> f32 { if val < 0.0 { -((-val).powf(4.0 / 3.0)) } else { val.powf(4.0 / 3.0) } } #[inline(always)] fn requant(val: f32, scale: f32) -> f32 { if scale == 0.0 { return 0.0; } let bval = val / scale; if bval >= 0.0 { val.powf(3.0 / 4.0) } else { -((-val).powf(3.0 / 4.0)) } } #[derive(Clone, Copy)] #[allow(dead_code)] pub struct Pulse { number_pulse: usize, pulse_start_sfb: usize, pulse_offset: [u8; 4], pulse_amp: [u8; 4], } impl Pulse { pub fn read(bs: &mut B) -> Result> { let pulse_data_present = bs.read_bool()?; if !pulse_data_present { return Ok(None); } let number_pulse = bs.read_bits_leq32(2)? as usize + 1; let pulse_start_sfb = bs.read_bits_leq32(6)? as usize; let mut pulse_offset: [u8; 4] = [0; 4]; let mut pulse_amp: [u8; 4] = [0; 4]; for i in 0..number_pulse { pulse_offset[i] = bs.read_bits_leq32(5)? as u8; pulse_amp[i] = bs.read_bits_leq32(4)? as u8; } Ok(Some(Self { number_pulse, pulse_start_sfb, pulse_offset, pulse_amp })) } pub fn synth( &self, bands: &[usize], scales: &[[f32; MAX_SFBS]; MAX_WINDOWS], coeffs: &mut [f32; 1024], ) { if self.pulse_start_sfb >= bands.len() - 1 { return; } let mut k = bands[self.pulse_start_sfb]; let mut band = self.pulse_start_sfb; for pno in 0..self.number_pulse { k += self.pulse_offset[pno] as usize; if k >= 1024 { return; } while bands[band + 1] <= k { band += 1; } let scale = scales[0][band]; let mut base = coeffs[k]; if base != 0.0 { base = requant(coeffs[k], scale); } if base > 0.0 { base += f32::from(self.pulse_amp[pno]); } else { base -= f32::from(self.pulse_amp[pno]); } coeffs[k] = iquant(base) * scale; } } } symphonia-codec-aac-0.5.4/src/aac/ics/tns.rs000064400000000000000000000137341046102023000167110ustar 00000000000000// Symphonia // Copyright (c) 2019-2022 The Project Symphonia Developers. // // Previous Author: Kostya Shishkov // // This source file includes code originally written for the NihAV // project. With the author's permission, it has been relicensed for, // and ported to the Symphonia project. // // 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 std::f32::consts; use crate::aac::common::*; use crate::aac::ics::IcsInfo; const TNS_MAX_ORDER: usize = 20; const TNS_MAX_LONG_BANDS: [usize; 12] = [31, 31, 34, 40, 42, 51, 46, 46, 42, 42, 42, 39]; const TNS_MAX_SHORT_BANDS: [usize; 12] = [9, 9, 10, 14, 14, 14, 14, 14, 14, 14, 14, 14]; #[derive(Copy, Clone)] struct TnsCoeffs { length: usize, order: usize, direction: bool, coef: [f32; TNS_MAX_ORDER + 1], } impl TnsCoeffs { fn new() -> Self { Self { length: 0, order: 0, direction: false, coef: [0.0; TNS_MAX_ORDER + 1] } } fn read( &mut self, bs: &mut B, long_win: bool, coef_res: bool, max_order: usize, ) -> Result<()> { self.length = bs.read_bits_leq32(if long_win { 6 } else { 4 })? as usize; self.order = bs.read_bits_leq32(if long_win { 5 } else { 3 })? as usize; validate!(self.order <= max_order); if self.order > 0 { self.direction = bs.read_bool()?; let coef_compress = bs.read_bool()?; // If coef_res is true, then the transmitted resolution of the filter coefficients // is 4 bits, otherwise it's 3 (4.6.9.2). let mut coef_res_bits = if coef_res { 4 } else { 3 }; // If true, the most significant bit of the filter coefficient is not transmitted // (4.6.9.2). if coef_compress { coef_res_bits -= 1; } let sign_mask = 1 << (coef_res_bits - 1); let neg_mask = !((1 << coef_res_bits) - 1); // Derived from `1 << (coef_res_bits - 1)` before compression. let fac_base = if coef_res { 8.0 } else { 4.0 }; let iqfac = (fac_base - 0.5) / consts::FRAC_PI_2; let iqfac_m = (fac_base + 0.5) / consts::FRAC_PI_2; let mut tmp: [f32; TNS_MAX_ORDER] = [0.0; TNS_MAX_ORDER]; for el in tmp[..self.order].iter_mut() { let val = bs.read_bits_leq32(coef_res_bits)? as u8; // Convert to signed integer. let c = f32::from(if (val & sign_mask) != 0 { (val | neg_mask) as i8 } else { val as i8 }); *el = (if c >= 0.0 { c / iqfac } else { c / iqfac_m }).sin(); } // Generate LPC coefficients let mut b: [f32; TNS_MAX_ORDER + 1] = [0.0; TNS_MAX_ORDER + 1]; for m in 1..=self.order { for i in 1..m { b[i] = self.coef[i - 1] + tmp[m - 1] * self.coef[m - i - 1]; } self.coef[..(m - 1)].copy_from_slice(&b[1..m]); self.coef[m - 1] = tmp[m - 1]; } } Ok(()) } } #[derive(Copy, Clone)] pub struct Tns { n_filt: [usize; MAX_WINDOWS], coeffs: [[TnsCoeffs; 4]; MAX_WINDOWS], } impl Tns { pub fn read(bs: &mut B, info: &IcsInfo, is_lc: bool) -> Result> { let tns_data_present = bs.read_bool()?; if !tns_data_present { return Ok(None); } // Table 4.156 let max_order = if !info.long_win { 7 } else if is_lc { 12 } else { TNS_MAX_ORDER }; let mut n_filt: [usize; MAX_WINDOWS] = [0; MAX_WINDOWS]; let mut coeffs: [[TnsCoeffs; 4]; MAX_WINDOWS] = [[TnsCoeffs::new(); 4]; MAX_WINDOWS]; for w in 0..info.num_windows { n_filt[w] = bs.read_bits_leq32(if info.long_win { 2 } else { 1 })? as usize; let coef_res = if n_filt[w] != 0 { bs.read_bool()? } else { false }; for filt in 0..n_filt[w] { coeffs[w][filt].read(bs, info.long_win, coef_res, max_order)?; } } Ok(Some(Self { n_filt, coeffs })) } pub fn synth( &self, info: &IcsInfo, bands: &[usize], rate_idx: usize, coeffs: &mut [f32; 1024], ) { let tns_max_bands = (if info.long_win { TNS_MAX_LONG_BANDS[rate_idx] } else { TNS_MAX_SHORT_BANDS[rate_idx] }) .min(info.max_sfb); for w in 0..info.num_windows { let mut bottom = bands.len() - 1; for f in 0..self.n_filt[w] { let top = bottom; bottom = if top > self.coeffs[w][f].length { top - self.coeffs[w][f].length } else { 0 }; let order = self.coeffs[w][f].order; if order == 0 { continue; } let start = w * 128 + bands[bottom.min(tns_max_bands)]; let end = w * 128 + bands[top.min(tns_max_bands)]; let lpc = &self.coeffs[w][f].coef; if !self.coeffs[w][f].direction { for (m, i) in (start..end).enumerate() { for j in 0..order.min(m) { coeffs[i] -= coeffs[i - j - 1] * lpc[j]; } } } else { for (m, i) in (start..end).rev().enumerate() { for j in 0..order.min(m) { coeffs[i] -= coeffs[i + j + 1] * lpc[j]; } } } } } } } symphonia-codec-aac-0.5.4/src/aac/mod.rs000064400000000000000000000411031046102023000160750ustar 00000000000000// Symphonia // Copyright (c) 2019-2022 The Project Symphonia Developers. // // Previous Author: Kostya Shishkov // // This source file includes code originally written for the NihAV // project. With the author's permission, it has been relicensed for, // and ported to the Symphonia project. // // 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, SignalSpec}; use symphonia_core::codecs::{CodecDescriptor, CodecParameters, CODEC_TYPE_AAC}; use symphonia_core::codecs::{Decoder, DecoderOptions, FinalizeResult}; use symphonia_core::errors::{unsupported_error, Result}; use symphonia_core::formats::Packet; use symphonia_core::io::{BitReaderLtr, FiniteBitStream, ReadBitsLtr}; use symphonia_core::support_codec; use symphonia_core::units::Duration; mod codebooks; mod common; mod cpe; mod dsp; mod ics; mod window; use crate::common::*; use common::*; struct M4AInfo { otype: M4AType, srate: u32, channels: usize, samples: usize, sbr_ps_info: Option<(u32, usize)>, sbr_present: bool, ps_present: bool, } impl M4AInfo { fn new() -> Self { Self { otype: M4AType::None, srate: 0, channels: 0, samples: 0, sbr_ps_info: Option::None, sbr_present: false, ps_present: false, } } fn read_object_type(bs: &mut B) -> Result { let otypeidx = match bs.read_bits_leq32(5)? { idx if idx < 31 => idx as usize, 31 => (bs.read_bits_leq32(6)? + 32) as usize, _ => unreachable!(), }; if otypeidx >= M4A_TYPES.len() { Ok(M4AType::Unknown) } else { Ok(M4A_TYPES[otypeidx]) } } fn read_sampling_frequency(bs: &mut B) -> Result { match bs.read_bits_leq32(4)? { idx if idx < 15 => Ok(AAC_SAMPLE_RATES[idx as usize]), _ => { let srate = (0xf << 20) & bs.read_bits_leq32(20)?; Ok(srate) } } } fn read_channel_config(bs: &mut B) -> Result { let chidx = bs.read_bits_leq32(4)? as usize; if chidx < AAC_CHANNELS.len() { Ok(AAC_CHANNELS[chidx]) } else { Ok(chidx) } } fn read(&mut self, buf: &[u8]) -> Result<()> { let mut bs = BitReaderLtr::new(buf); self.otype = Self::read_object_type(&mut bs)?; self.srate = Self::read_sampling_frequency(&mut bs)?; validate!(self.srate > 0); self.channels = Self::read_channel_config(&mut bs)?; if (self.otype == M4AType::Sbr) || (self.otype == M4AType::PS) { let ext_srate = Self::read_sampling_frequency(&mut bs)?; self.otype = Self::read_object_type(&mut bs)?; let ext_chans = if self.otype == M4AType::ER_BSAC { Self::read_channel_config(&mut bs)? } else { 0 }; self.sbr_ps_info = Some((ext_srate, ext_chans)); } match self.otype { M4AType::Main | M4AType::Lc | M4AType::Ssr | M4AType::Scalable | M4AType::TwinVQ | M4AType::ER_AAC_LC | M4AType::ER_AAC_LTP | M4AType::ER_AAC_Scalable | M4AType::ER_TwinVQ | M4AType::ER_BSAC | M4AType::ER_AAC_LD => { // GASpecificConfig let short_frame = bs.read_bool()?; self.samples = if short_frame { 960 } else { 1024 }; let depends_on_core = bs.read_bool()?; if depends_on_core { let _delay = bs.read_bits_leq32(14)?; } let extension_flag = bs.read_bool()?; if self.channels == 0 { return unsupported_error("aac: program config element"); } if (self.otype == M4AType::Scalable) || (self.otype == M4AType::ER_AAC_Scalable) { let _layer = bs.read_bits_leq32(3)?; } if extension_flag { if self.otype == M4AType::ER_BSAC { let _num_subframes = bs.read_bits_leq32(5)? as usize; let _layer_length = bs.read_bits_leq32(11)?; } if (self.otype == M4AType::ER_AAC_LC) || (self.otype == M4AType::ER_AAC_LTP) || (self.otype == M4AType::ER_AAC_Scalable) || (self.otype == M4AType::ER_AAC_LD) { let _section_data_resilience = bs.read_bool()?; let _scalefactors_resilience = bs.read_bool()?; let _spectral_data_resilience = bs.read_bool()?; } let extension_flag3 = bs.read_bool()?; if extension_flag3 { return unsupported_error("aac: version3 extensions"); } } } M4AType::Celp => { return unsupported_error("aac: CELP config"); } M4AType::Hvxc => { return unsupported_error("aac: HVXC config"); } M4AType::Ttsi => { return unsupported_error("aac: TTS config"); } M4AType::MainSynth | M4AType::WavetableSynth | M4AType::GeneralMIDI | M4AType::Algorithmic => { return unsupported_error("aac: structured audio config"); } M4AType::ER_CELP => { return unsupported_error("aac: ER CELP config"); } M4AType::ER_HVXC => { return unsupported_error("aac: ER HVXC config"); } M4AType::ER_HILN | M4AType::ER_Parametric => { return unsupported_error("aac: parametric config"); } M4AType::Ssc => { return unsupported_error("aac: SSC config"); } M4AType::MPEGSurround => { // bs.ignore_bits(1)?; // sacPayloadEmbedding return unsupported_error("aac: MPEG Surround config"); } M4AType::Layer1 | M4AType::Layer2 | M4AType::Layer3 => { return unsupported_error("aac: MPEG Layer 1/2/3 config"); } M4AType::Dst => { return unsupported_error("aac: DST config"); } M4AType::Als => { // bs.ignore_bits(5)?; // fillBits return unsupported_error("aac: ALS config"); } M4AType::Sls | M4AType::SLSNonCore => { return unsupported_error("aac: SLS config"); } M4AType::ER_AAC_ELD => { return unsupported_error("aac: ELD config"); } M4AType::SMRSimple | M4AType::SMRMain => { return unsupported_error("aac: symbolic music config"); } _ => {} }; match self.otype { M4AType::ER_AAC_LC | M4AType::ER_AAC_LTP | M4AType::ER_AAC_Scalable | M4AType::ER_TwinVQ | M4AType::ER_BSAC | M4AType::ER_AAC_LD | M4AType::ER_CELP | M4AType::ER_HVXC | M4AType::ER_HILN | M4AType::ER_Parametric | M4AType::ER_AAC_ELD => { let ep_config = bs.read_bits_leq32(2)?; if (ep_config == 2) || (ep_config == 3) { return unsupported_error("aac: error protection config"); } // if ep_config == 3 { // let direct_mapping = bs.read_bit()?; // validate!(direct_mapping); // } } _ => {} }; if self.sbr_ps_info.is_some() && (bs.bits_left() >= 16) { let sync = bs.read_bits_leq32(11)?; if sync == 0x2B7 { let ext_otype = Self::read_object_type(&mut bs)?; if ext_otype == M4AType::Sbr { self.sbr_present = bs.read_bool()?; if self.sbr_present { let _ext_srate = Self::read_sampling_frequency(&mut bs)?; if bs.bits_left() >= 12 { let sync = bs.read_bits_leq32(11)?; if sync == 0x548 { self.ps_present = bs.read_bool()?; } } } } if ext_otype == M4AType::PS { self.sbr_present = bs.read_bool()?; if self.sbr_present { let _ext_srate = Self::read_sampling_frequency(&mut bs)?; } let _ext_channels = bs.read_bits_leq32(4)?; } } } Ok(()) } } impl std::fmt::Display for M4AInfo { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( f, "MPEG 4 Audio {}, {} Hz, {} channels, {} samples per frame", self.otype, self.srate, self.channels, self.samples ) } } /// Advanced Audio Coding (AAC) decoder. /// /// Implements a decoder for Advanced Audio Decoding Low-Complexity (AAC-LC) as defined in /// ISO/IEC 13818-7 and ISO/IEC 14496-3. pub struct AacDecoder { // info: NACodecInfoRef, m4ainfo: M4AInfo, pairs: Vec, dsp: dsp::Dsp, sbinfo: GASubbandInfo, params: CodecParameters, buf: AudioBuffer, } impl AacDecoder { fn set_pair(&mut self, pair_no: usize, channel: usize, pair: bool) -> Result<()> { if self.pairs.len() <= pair_no { self.pairs.push(cpe::ChannelPair::new(pair, channel, self.sbinfo)); } else { validate!(self.pairs[pair_no].channel == channel); validate!(self.pairs[pair_no].is_pair == pair); } validate!(if pair { channel + 1 } else { channel } < self.m4ainfo.channels); Ok(()) } fn decode_ga(&mut self, bs: &mut B) -> Result<()> { let mut cur_pair = 0; let mut cur_ch = 0; while bs.bits_left() > 3 { let id = bs.read_bits_leq32(3)?; match id { 0 => { // ID_SCE let _tag = bs.read_bits_leq32(4)?; self.set_pair(cur_pair, cur_ch, false)?; self.pairs[cur_pair].decode_ga_sce(bs, self.m4ainfo.otype)?; cur_pair += 1; cur_ch += 1; } 1 => { // ID_CPE let _tag = bs.read_bits_leq32(4)?; self.set_pair(cur_pair, cur_ch, true)?; self.pairs[cur_pair].decode_ga_cpe(bs, self.m4ainfo.otype)?; cur_pair += 1; cur_ch += 2; } 2 => { // ID_CCE return unsupported_error("aac: coupling channel element"); } 3 => { // ID_LFE let _tag = bs.read_bits_leq32(4)?; self.set_pair(cur_pair, cur_ch, false)?; self.pairs[cur_pair].decode_ga_sce(bs, self.m4ainfo.otype)?; cur_pair += 1; cur_ch += 1; } 4 => { // ID_DSE let _id = bs.read_bits_leq32(4)?; let align = bs.read_bool()?; let mut count = bs.read_bits_leq32(8)?; if count == 255 { count += bs.read_bits_leq32(8)?; } if align { bs.realign(); // ???? } bs.ignore_bits(count * 8)?; // no SBR payload or such } 5 => { // ID_PCE return unsupported_error("aac: program config"); } 6 => { // ID_FIL let mut count = bs.read_bits_leq32(4)? as usize; if count == 15 { count += bs.read_bits_leq32(8)? as usize; count -= 1; } for _ in 0..count { // ext payload bs.ignore_bits(8)?; } } 7 => { // ID_TERM break; } _ => unreachable!(), }; } let rate_idx = GASubbandInfo::find_idx(self.m4ainfo.srate); for pair in 0..cur_pair { self.pairs[pair].synth_audio(&mut self.dsp, &mut self.buf, rate_idx); } Ok(()) } // fn flush(&mut self) { // for pair in self.pairs.iter_mut() { // pair.ics[0].delay = [0.0; 1024]; // pair.ics[1].delay = [0.0; 1024]; // } // } fn decode_inner(&mut self, packet: &Packet) -> Result<()> { // Clear the audio output buffer. self.buf.clear(); self.buf.render_reserved(None); let mut bs = BitReaderLtr::new(packet.buf()); // Choose decode step based on the object type. match self.m4ainfo.otype { M4AType::Lc => self.decode_ga(&mut bs)?, _ => return unsupported_error("aac: object type"), } Ok(()) } } impl Decoder for AacDecoder { fn try_new(params: &CodecParameters, _: &DecoderOptions) -> Result { // This decoder only supports AAC. if params.codec != CODEC_TYPE_AAC { return unsupported_error("aac: invalid codec type"); } let mut m4ainfo = M4AInfo::new(); // If extra data present, parse the audio specific config if let Some(extra_data_buf) = ¶ms.extra_data { validate!(extra_data_buf.len() >= 2); m4ainfo.read(extra_data_buf)?; } else { // Otherwise, assume there is no ASC and use the codec parameters for ADTS. m4ainfo.otype = M4AType::Lc; m4ainfo.samples = 1024; m4ainfo.srate = match params.sample_rate { Some(rate) => rate, None => return unsupported_error("aac: sample rate is required"), }; m4ainfo.channels = if let Some(channels) = params.channels { channels.count() } else if let Some(layout) = params.channel_layout { layout.into_channels().count() } else { return unsupported_error("aac: channels or channel layout is required"); }; } //print!("edata:"); for s in edata.iter() { print!(" {:02X}", *s);}println!(""); if (m4ainfo.otype != M4AType::Lc) || (m4ainfo.channels > 2) || (m4ainfo.samples != 1024) { return unsupported_error("aac: aac too complex"); } let spec = SignalSpec::new(m4ainfo.srate, map_channels(m4ainfo.channels as u32).unwrap()); let duration = m4ainfo.samples as Duration; let srate = m4ainfo.srate; Ok(AacDecoder { m4ainfo, pairs: Vec::new(), dsp: dsp::Dsp::new(), sbinfo: GASubbandInfo::find(srate), params: params.clone(), buf: AudioBuffer::new(duration, spec), }) } fn reset(&mut self) { for pair in self.pairs.iter_mut() { pair.reset(); } } fn supported_codecs() -> &'static [CodecDescriptor] { &[support_codec!(CODEC_TYPE_AAC, "aac", "Advanced Audio Coding")] } fn codec_params(&self) -> &CodecParameters { &self.params } 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-codec-aac-0.5.4/src/aac/window.rs000064400000000000000000000040171046102023000166300ustar 00000000000000// Symphonia // Copyright (c) 2019-2022 The Project Symphonia Developers. // // Previous Author: Kostya Shishkov // // This source file includes code originally written for the NihAV // project. With the author's permission, it has been relicensed for, // and ported to the Symphonia project. // // 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::f32::consts; /// Window types. #[derive(Debug, Clone, Copy, PartialEq)] pub enum WindowType { /// Simple sine window. Sine, /// Kaiser-Bessel derived window. KaiserBessel(f32), } /// Calculates window coefficients for the requested window type and size. /// /// Set `half` flag to calculate only the first half of the window. pub fn generate_window(mode: WindowType, scale: f32, size: usize, half: bool, dst: &mut [f32]) { match mode { WindowType::Sine => { let param = if half { consts::PI / ((2 * size) as f32) } else { consts::PI / (size as f32) }; for n in 0..size { dst[n] = (((n as f32) + 0.5) * param).sin() * scale; } } WindowType::KaiserBessel(alpha) => { let dlen = if half { size as f32 } else { (size as f32) * 0.5 }; let alpha2 = f64::from((alpha * consts::PI / dlen) * (alpha * consts::PI / dlen)); let mut kb: Vec = Vec::with_capacity(size); let mut sum = 0.0; for n in 0..size { let b = bessel_i0(((n * (size - n)) as f64) * alpha2); sum += b; kb.push(sum); } sum += 1.0; for n in 0..size { dst[n] = (kb[n] / sum).sqrt() as f32; } } }; } fn bessel_i0(inval: f64) -> f64 { let mut val: f64 = 1.0; for n in (1..64).rev() { val *= inval / f64::from(n * n); val += 1.0; } val } symphonia-codec-aac-0.5.4/src/adts.rs000064400000000000000000000201231046102023000155240ustar 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::unsupported_error; use symphonia_core::support_format; use symphonia_core::audio::Channels; use symphonia_core::codecs::{CodecParameters, CODEC_TYPE_AAC}; use symphonia_core::errors::{decode_error, 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 std::io::{Seek, SeekFrom}; use super::common::{map_channels, M4AType, AAC_SAMPLE_RATES, M4A_TYPES}; use log::debug; const SAMPLES_PER_AAC_PACKET: u64 = 1024; /// Audio Data Transport Stream (ADTS) format reader. /// /// `AdtsReader` implements a demuxer for ADTS (AAC native frames). pub struct AdtsReader { reader: MediaSourceStream, tracks: Vec, cues: Vec, metadata: MetadataLog, first_frame_pos: u64, next_packet_ts: u64, } impl QueryDescriptor for AdtsReader { fn query() -> &'static [Descriptor] { &[support_format!( "aac", "Audio Data Transport Stream (native AAC)", &["aac"], &["audio/aac"], &[&[0xff, 0xf1]] )] } fn score(_context: &[u8]) -> u8 { 255 } } #[derive(Debug)] #[allow(dead_code)] struct AdtsHeader { profile: M4AType, channels: Option, sample_rate: u32, frame_len: usize, } impl AdtsHeader { const SIZE: usize = 7; fn sync(reader: &mut B) -> Result<()> { let mut sync = 0u16; while sync != 0xfff1 { sync = (sync << 8) | u16::from(reader.read_u8()?); } Ok(()) } fn read(reader: &mut B) -> Result { AdtsHeader::sync(reader)?; // The header may be 5 or 7 bytes (without or with protection). let mut buf = [0u8; 7]; reader.read_buf_exact(&mut buf[..5])?; let mut bs = BitReaderLtr::new(&buf); // Profile let profile = M4A_TYPES[bs.read_bits_leq32(2)? as usize + 1]; // Sample rate index. let sample_rate = match bs.read_bits_leq32(4)? as usize { 15 => return decode_error("adts: forbidden sample rate"), 13 | 14 => return decode_error("adts: reserved sample rate"), idx => AAC_SAMPLE_RATES[idx], }; // Private bit. bs.ignore_bit()?; // Channel configuration let channels = match bs.read_bits_leq32(3)? { 0 => None, idx => map_channels(idx), }; // Originality, Home, Copyrighted ID bit, Copyright ID start bits. Only used for encoding. bs.ignore_bits(4)?; // Frame length = Header size (7) + AAC frame size let frame_len = bs.read_bits_leq32(13)? as usize; if frame_len < AdtsHeader::SIZE { return decode_error("adts: invalid adts frame length"); } let _fullness = bs.read_bits_leq32(11)?; let num_aac_frames = bs.read_bits_leq32(2)? + 1; // TODO: Support multiple AAC packets per ADTS packet. if num_aac_frames > 1 { return unsupported_error("adts: only 1 aac frame per adts packet is supported"); } Ok(AdtsHeader { profile, channels, sample_rate, frame_len: frame_len - AdtsHeader::SIZE }) } } impl FormatReader for AdtsReader { fn try_new(mut source: MediaSourceStream, _options: &FormatOptions) -> Result { let header = AdtsHeader::read(&mut source)?; // Use the header to populate the codec parameters. let mut params = CodecParameters::new(); params.for_codec(CODEC_TYPE_AAC).with_sample_rate(header.sample_rate); if let Some(channels) = header.channels { params.with_channels(channels); } // Rewind back to the start of the frame. source.seek_buffered_rev(AdtsHeader::SIZE); let first_frame_pos = source.pos(); Ok(AdtsReader { reader: source, tracks: vec![Track::new(0, params)], cues: Vec::new(), metadata: Default::default(), first_frame_pos, next_packet_ts: 0, }) } fn next_packet(&mut self) -> Result { // Parse the header to get the calculated frame size. let header = AdtsHeader::read(&mut self.reader)?; // TODO: Support multiple AAC packets per ADTS packet. let ts = self.next_packet_ts; self.next_packet_ts += SAMPLES_PER_AAC_PACKET; Ok(Packet::new_from_boxed_slice( 0, ts, SAMPLES_PER_AAC_PACKET, self.reader.read_boxed_slice_exact(header.frame_len)?, )) } 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 { // Get the timestamp of the desired audio frame. let required_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); } } }; debug!("seeking to ts={}", required_ts); // If the desired timestamp is less-than the next packet timestamp, attempt to seek // to the start of the stream. if required_ts < self.next_packet_ts { // If the reader is not seekable then only forward seeks are possible. if self.reader.is_seekable() { let seeked_pos = self.reader.seek(SeekFrom::Start(self.first_frame_pos))?; // Since the elementary stream has no timestamp information, the position seeked // to must be exactly as requested. if seeked_pos != self.first_frame_pos { return seek_error(SeekErrorKind::Unseekable); } } else { return seek_error(SeekErrorKind::ForwardOnly); } // Successfuly seeked to the start of the stream, reset the next packet timestamp. self.next_packet_ts = 0; } // Parse frames from the stream until the frame containing the desired timestamp is // reached. loop { // Parse the next frame header. let header = AdtsHeader::read(&mut self.reader)?; // TODO: Support multiple AAC packets per ADTS packet. // 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 + SAMPLES_PER_AAC_PACKET > required_ts { self.reader.seek_buffered_rev(AdtsHeader::SIZE); break; } // Otherwise, ignore the frame body. self.reader.ignore_bytes(header.frame_len as u64)?; // Increment the timestamp for the next packet. self.next_packet_ts += SAMPLES_PER_AAC_PACKET; } debug!( "seeked to ts={} (delta={})", self.next_packet_ts, required_ts as i64 - self.next_packet_ts as i64 ); Ok(SeekedTo { track_id: 0, required_ts, actual_ts: self.next_packet_ts }) } fn into_inner(self: Box) -> MediaSourceStream { self.reader } } symphonia-codec-aac-0.5.4/src/common.rs000064400000000000000000000111211046102023000160570ustar 00000000000000// Symphonia // Copyright (c) 2019-2022 The Project Symphonia Developers. // // Previous Author: Kostya Shishkov // // This source file includes code originally written for the NihAV // project. With the author's permission, it has been relicensed for, // and ported to the Symphonia project. // // 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::Channels; #[allow(non_camel_case_types)] #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum M4AType { None, Main, Lc, Ssr, Ltp, Sbr, Scalable, TwinVQ, Celp, Hvxc, Ttsi, MainSynth, WavetableSynth, GeneralMIDI, Algorithmic, ER_AAC_LC, ER_AAC_LTP, ER_AAC_Scalable, ER_TwinVQ, ER_BSAC, ER_AAC_LD, ER_CELP, ER_HVXC, ER_HILN, ER_Parametric, Ssc, PS, MPEGSurround, Layer1, Layer2, Layer3, Dst, Als, Sls, SLSNonCore, ER_AAC_ELD, SMRSimple, SMRMain, Reserved, Unknown, } impl std::fmt::Display for M4AType { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", M4A_TYPE_NAMES[*self as usize]) } } pub const M4A_TYPES: &[M4AType] = &[ M4AType::None, M4AType::Main, M4AType::Lc, M4AType::Ssr, M4AType::Ltp, M4AType::Sbr, M4AType::Scalable, M4AType::TwinVQ, M4AType::Celp, M4AType::Hvxc, M4AType::Reserved, M4AType::Reserved, M4AType::Ttsi, M4AType::MainSynth, M4AType::WavetableSynth, M4AType::GeneralMIDI, M4AType::Algorithmic, M4AType::ER_AAC_LC, M4AType::Reserved, M4AType::ER_AAC_LTP, M4AType::ER_AAC_Scalable, M4AType::ER_TwinVQ, M4AType::ER_BSAC, M4AType::ER_AAC_LD, M4AType::ER_CELP, M4AType::ER_HVXC, M4AType::ER_HILN, M4AType::ER_Parametric, M4AType::Ssc, M4AType::PS, M4AType::MPEGSurround, M4AType::Reserved, /*escape*/ M4AType::Layer1, M4AType::Layer2, M4AType::Layer3, M4AType::Dst, M4AType::Als, M4AType::Sls, M4AType::SLSNonCore, M4AType::ER_AAC_ELD, M4AType::SMRSimple, M4AType::SMRMain, ]; pub const M4A_TYPE_NAMES: &[&str] = &[ "None", "AAC Main", "AAC LC", "AAC SSR", "AAC LTP", "SBR", "AAC Scalable", "TwinVQ", "CELP", "HVXC", // "(reserved10)", // "(reserved11)", "TTSI", "Main synthetic", "Wavetable synthesis", "General MIDI", "Algorithmic Synthesis and Audio FX", "ER AAC LC", // "(reserved18)", "ER AAC LTP", "ER AAC Scalable", "ER TwinVQ", "ER BSAC", "ER AAC LD", "ER CELP", "ER HVXC", "ER HILN", "ER Parametric", "SSC", "PS", "MPEG Surround", // "(escape)", "Layer-1", "Layer-2", "Layer-3", "DST", "ALS", "SLS", "SLS non-core", "ER AAC ELD", "SMR Simple", "SMR Main", "(reserved)", "(unknown)", ]; pub const AAC_SAMPLE_RATES: [u32; 16] = [ 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350, 0, 0, 0, ]; pub const AAC_CHANNELS: [usize; 8] = [0, 1, 2, 3, 4, 5, 6, 8]; pub fn map_channels(channels: u32) -> Option { match channels { 0 => None, 1 => Some(Channels::FRONT_LEFT), 2 => Some(Channels::FRONT_LEFT | Channels::FRONT_RIGHT), 3 => Some(Channels::FRONT_CENTRE | Channels::FRONT_LEFT | Channels::FRONT_RIGHT), 4 => Some( Channels::FRONT_CENTRE | Channels::FRONT_LEFT | Channels::FRONT_RIGHT | Channels::REAR_CENTRE, ), 5 => Some( Channels::FRONT_CENTRE | Channels::FRONT_LEFT | Channels::FRONT_RIGHT | Channels::SIDE_LEFT | Channels::SIDE_RIGHT, ), 6 => Some( Channels::FRONT_CENTRE | Channels::FRONT_LEFT | Channels::FRONT_RIGHT | Channels::SIDE_LEFT | Channels::SIDE_RIGHT | Channels::LFE1, ), 7 => None, 8 => Some( Channels::FRONT_CENTRE | Channels::FRONT_LEFT | Channels::FRONT_RIGHT | Channels::SIDE_LEFT | Channels::SIDE_RIGHT | Channels::FRONT_LEFT_WIDE | Channels::FRONT_RIGHT_WIDE | Channels::LFE1, ), _ => None, } } symphonia-codec-aac-0.5.4/src/lib.rs000064400000000000000000000013641046102023000153450ustar 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)] // TODO: Remove this when refactoring AAC. #![allow(clippy::needless_range_loop)] mod aac; mod adts; mod common; pub use aac::AacDecoder; pub use adts::AdtsReader; symphonia-codec-aac-0.5.4/tests/tests.rs000064400000000000000000000020661046102023000163140ustar 00000000000000use symphonia_codec_aac::{AacDecoder, AdtsReader}; use symphonia_core::codecs::{CodecParameters, Decoder, DecoderOptions, CODEC_TYPE_AAC}; use symphonia_core::errors; use symphonia_core::formats::{FormatOptions, FormatReader}; use symphonia_core::io::MediaSourceStream; fn test_decode(data: Vec) -> symphonia_core::errors::Result<()> { let data = std::io::Cursor::new(data); let source = MediaSourceStream::new(Box::new(data), Default::default()); let mut reader = AdtsReader::try_new(source, &FormatOptions::default())?; let mut decoder = AacDecoder::try_new( CodecParameters::new().for_codec(CODEC_TYPE_AAC), &DecoderOptions::default(), )?; loop { let packet = reader.next_packet()?; let _ = decoder.decode(&packet); } } #[test] fn invalid_channels_aac() { let file = vec![ 0xff, 0xf1, 0xaf, 0xce, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfb, 0xaf, ]; let err = test_decode(file).unwrap_err(); assert!(matches!(err, errors::Error::Unsupported(_))); }