symphonia-codec-aac-0.5.2/.cargo_vcs_info.json0000644000000001610000000000100146420ustar { "git": { "sha1": "412f44daab39920beeb81d78b0e4271b263d33e9" }, "path_in_vcs": "symphonia-codec-aac" }symphonia-codec-aac-0.5.2/Cargo.toml0000644000000022470000000000100126470ustar # 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.2" 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.2" symphonia-codec-aac-0.5.2/Cargo.toml.orig000064400000000000000000000012241046102023000163220ustar 00000000000000[package] name = "symphonia-codec-aac" version = "0.5.2" 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.2", path = "../symphonia-core" }symphonia-codec-aac-0.5.2/README.md000064400000000000000000000021141046102023000147110ustar 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 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-codec-aac-0.5.2/src/aac/codebooks.rs000075500000000000000000000635241046102023000173020ustar 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).into_iter().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()).into_iter().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).into_iter().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.2/src/aac/common.rs000064400000000000000000000144041046102023000166100ustar 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.2/src/aac/cpe.rs000064400000000000000000000133631046102023000160720ustar 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.2/src/aac/dsp.rs000064400000000000000000000131621046102023000161060ustar 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_mut(256)) { self.imdct_short.imdct(ain, aout); } // Zero the eight short sequence buffer. self.pcm_short = [0.0; 1152]; 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]; } for i in SHORT_WIN_POINT1..1024 { delay[i] = 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)]; } for i in SHORT_WIN_POINT1..1024 { delay[i] = 0.0; } } _ => unreachable!(), }; } } symphonia-codec-aac-0.5.2/src/aac/ics/gain.rs000064400000000000000000000022751046102023000170170ustar 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.2/src/aac/ics/ltp.rs000064400000000000000000000033241046102023000166740ustar 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.2/src/aac/ics/mod.rs000064400000000000000000000417761046102023000166710ustar 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::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; 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 }; } #[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], } const INTENSITY_SCALE_MIN: i16 = -155; const NOISE_SCALE_MIN: i16 = -100; #[inline(always)] fn get_scale(scale: i16) -> f32 { 2.0f32.powf(0.25 * f32::from(scale - 56)) // 2.0f32.powf(0.25 * (f32::from(scale) - 100.0 - 56.0)) } #[inline(always)] fn get_intensity_scale(scale: i16) -> f32 { 0.5f32.powf(0.25 * f32::from(scale)) } 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 = 0i16; let mut scf_noise = i16::from(self.global_gain) - 90; let mut scf_normal = i16::from(self.global_gain); let scf_cb = &codebooks::SCALEFACTORS; 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; validate!( (scf_intensity >= INTENSITY_SCALE_MIN) && (scf_intensity < INTENSITY_SCALE_MIN + 256) ); get_intensity_scale(scf_intensity) } 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; } validate!( (scf_noise >= NOISE_SCALE_MIN) && (scf_noise < NOISE_SCALE_MIN + 256) ); get_scale(scf_noise) } else { scf_normal += i16::from(bs.read_codebook(scf_cb)?.0) - 60; validate!((scf_normal >= 0) && (scf_normal < 256)); get_scale(scf_normal - 100) } } } 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 = [0.0; 1024]; 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.2/src/aac/ics/pulse.rs000064400000000000000000000055211046102023000172260ustar 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.2/src/aac/ics/tns.rs000064400000000000000000000137341046102023000167070ustar 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.2/src/aac/mod.rs000064400000000000000000000411031046102023000160730ustar 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.2/src/aac/window.rs000064400000000000000000000040171046102023000166260ustar 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.2/src/adts.rs000064400000000000000000000201231046102023000155220ustar 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.2/src/common.rs000064400000000000000000000111211046102023000160550ustar 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.2/src/lib.rs000064400000000000000000000013641046102023000153430ustar 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.2/tests/tests.rs000064400000000000000000000020661046102023000163120ustar 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(_))); }