# ------------------------------------------------------------ # AAC Coder/Decoder - Level 1 Wrappers + Demo # # Multimedia course at Aristotle University of # Thessaloniki (AUTh) # # Author: # Christos Choutouridis (ΑΕΜ 8997) # cchoutou@ece.auth.gr # # Description: # Level 1 wrapper module. # # This file provides: # - Thin wrappers for Level 1 API functions (encode/decode) that delegate # to the corresponding core implementations. # - A demo function that runs end-to-end and computes SNR. # - A small CLI entrypoint for convenience. # ------------------------------------------------------------ from __future__ import annotations from pathlib import Path from typing import Union import soundfile as sf from core.aac_types import AACSeq1, StereoSignal from core.aac_coder import aac_coder_1 as core_aac_coder_1 from core.aac_coder import aac_read_wav_stereo_48k from core.aac_decoder import aac_decoder_1 as core_aac_decoder_1 from core.aac_snr_db import snr_db # ----------------------------------------------------------------------------- # Public Level 1 API (wrappers) # ----------------------------------------------------------------------------- def aac_coder_1(filename_in: Union[str, Path]) -> AACSeq1: """ Level-1 AAC encoder (wrapper). Delegates to core implementation. Parameters ---------- filename_in : Union[str, Path] Input WAV filename. Assumption: stereo audio, sampling rate 48 kHz. Returns ------- AACSeq1 List of encoded frames (Level 1 schema). """ return core_aac_coder_1(filename_in) def aac_decoder_1(aac_seq_1: AACSeq1, filename_out: Union[str, Path]) -> StereoSignal: """ Level-1 AAC decoder (wrapper). Delegates to core implementation. Parameters ---------- aac_seq_1 : AACSeq1 Encoded sequence as produced by aac_coder_1(). filename_out : Union[str, Path] Output WAV filename. Assumption: 48 kHz, stereo. Returns ------- StereoSignal Decoded audio samples (time-domain), stereo, shape (N, 2), dtype float64. """ return core_aac_decoder_1(aac_seq_1, filename_out) # ----------------------------------------------------------------------------- # Demo (Level 1) # ----------------------------------------------------------------------------- def demo_aac_1(filename_in: Union[str, Path], filename_out: Union[str, Path]) -> float: """ Demonstration for the Level-1 codec. Runs: - aac_coder_1(filename_in) - aac_decoder_1(aac_seq_1, filename_out) and computes total SNR between original and decoded audio. Parameters ---------- filename_in : Union[str, Path] Input WAV filename (stereo, 48 kHz). filename_out : Union[str, Path] Output WAV filename (stereo, 48 kHz). Returns ------- float Overall SNR in dB. """ filename_in = Path(filename_in) filename_out = Path(filename_out) # Read original audio (reference) with the same validation as the codec. x_ref, fs_ref = aac_read_wav_stereo_48k(filename_in) if int(fs_ref) != 48000: raise ValueError("Input sampling rate must be 48 kHz.") # Encode / decode aac_seq_1 = aac_coder_1(filename_in) x_hat = aac_decoder_1(aac_seq_1, filename_out) # Optional sanity: ensure output file exists and is readable _, fs_hat = sf.read(str(filename_out), always_2d=True) if int(fs_hat) != 48000: raise ValueError("Decoded output sampling rate must be 48 kHz.") return snr_db(x_ref, x_hat) # ----------------------------------------------------------------------------- # CLI # ----------------------------------------------------------------------------- if __name__ == "__main__": # Example: # cd level_1 # python -m level_1 input.wav output.wav # or # python -m level_1 material/LicorDeCalandraca.wav LicorDeCalandraca_out.wav import sys if len(sys.argv) != 3: raise SystemExit("Usage: python -m level_1 ") in_wav = Path(sys.argv[1]) out_wav = Path(sys.argv[2]) print(f"Encoding/Decoding {in_wav} to {out_wav}") snr = demo_aac_1(in_wav, out_wav) print(f"SNR = {snr:.3f} dB")