Files
pmomusic/pmoaudio-ext/Cargo.toml

43 lines
1.3 KiB
TOML
Raw Normal View History

[package]
name = "pmoaudio-ext"
version = "0.1.0"
edition = "2024"
[dependencies]
# Core audio types
pmoaudio = { path = "../pmoaudio" }
pmocovers = { path = "../pmocovers"}
# Optional dependencies for cache-sink feature
pmoaudiocache = { path = "../pmoaudiocache", optional = true }
pmoflac = { path = "../pmoflac", optional = true }
pmometadata = { path = "../pmometadata", optional = true }
feat: Add PlaylistSource and ResamplingNode for playlist playback This commit implements a new audio source that reads from pmoplaylist and streams tracks continuously, along with a resampling node to normalize sample rates. ## New Components ### PlaylistSource (pmoaudio-ext) - New source in pmoaudio-ext/src/sources/playlist_source.rs - Reads from pmoplaylist ReadHandle - Decodes tracks from audio cache (pmoaudiocache) - Emits PCM with heterogeneous sample_rate and bit_depth - Polls playlist when empty (configurable interval, default 100ms) - Emits TrackBoundary markers between tracks - Graceful shutdown with EndOfStream on stop - Gated behind 'playlist' feature flag **Design Philosophy:** - Keeps each node simple (single responsibility) - Emits raw PCM without format normalization - Pipeline designer chooses how to handle heterogeneity - Ideal for Radio Paradise (homogeneous streams) - Requires ResamplingNode + ToI24Node for mixed playlists ### ResamplingNode (pmoaudio) - Generic resampling node in pmoaudio/src/nodes/resampling_node.rs - Normalizes variable sample rates to a target rate - Uses libsoxr for high-quality resampling - Automatically detects sample rate changes - Recreates resampler as needed - Preserves chunk type (I16/I24/I32/F32/F64) - Quality adapts to bit depth (Medium/High/Very High) ## Architecture PlaylistSource is placed in pmoaudio-ext to avoid circular dependencies: - pmoaudio-ext depends on: pmoaudio, pmoplaylist, pmoaudiocache - No reverse dependencies = clean dependency graph ## Configuration ### pmoaudio-ext/Cargo.toml - Updated 'playlist' feature to include pmoaudiocache, pmocache, pmoflac - Added sources module export ### pmoaudio - Added resampling_node module - Public export: ResamplingNode ## System Requirements ⚠️ **IMPORTANT**: libsoxr-dev must be installed for compilation See INSTALL_NOTES.md for installation instructions per platform. ## Usage Example ```rust // Radio Paradise (homogeneous 44.1kHz/16bit) let mut source = PlaylistSource::new(playlist, cache); let to_i24 = ToI24Node::new(); source.register(Box::new(to_i24)); // Mixed playlist (needs normalization) let mut source = PlaylistSource::new(playlist, cache); let mut resampler = ResamplingNode::new(48000); // Force 48kHz let to_i24 = ToI24Node::new(); source.register(Box::new(resampler)); resampler.register(Box::new(to_i24)); ``` ## Files Changed - pmoaudio-ext/Cargo.toml: Update playlist feature - pmoaudio-ext/src/lib.rs: Add sources module - pmoaudio-ext/src/sources/mod.rs: New sources module - pmoaudio-ext/src/sources/playlist_source.rs: New PlaylistSource (580 lines) - pmoaudio/src/nodes/resampling_node.rs: New ResamplingNode (350 lines) - pmoaudio/src/nodes/mod.rs: Register resampling_node - pmoaudio/src/lib.rs: Export ResamplingNode - INSTALL_NOTES.md: System requirements documentation ## Future Work - GapInsertionNode (inserts silence between tracks) - CrossfadeNode (fade-in/fade-out mixing) - Examples (deferred until implementation validated)
2025-11-05 13:44:24 +00:00
# Optional dependencies for playlist integration
pmoplaylist = { path = "../pmoplaylist", optional = true }
feat: Add PlaylistSource and ResamplingNode for playlist playback This commit implements a new audio source that reads from pmoplaylist and streams tracks continuously, along with a resampling node to normalize sample rates. ## New Components ### PlaylistSource (pmoaudio-ext) - New source in pmoaudio-ext/src/sources/playlist_source.rs - Reads from pmoplaylist ReadHandle - Decodes tracks from audio cache (pmoaudiocache) - Emits PCM with heterogeneous sample_rate and bit_depth - Polls playlist when empty (configurable interval, default 100ms) - Emits TrackBoundary markers between tracks - Graceful shutdown with EndOfStream on stop - Gated behind 'playlist' feature flag **Design Philosophy:** - Keeps each node simple (single responsibility) - Emits raw PCM without format normalization - Pipeline designer chooses how to handle heterogeneity - Ideal for Radio Paradise (homogeneous streams) - Requires ResamplingNode + ToI24Node for mixed playlists ### ResamplingNode (pmoaudio) - Generic resampling node in pmoaudio/src/nodes/resampling_node.rs - Normalizes variable sample rates to a target rate - Uses libsoxr for high-quality resampling - Automatically detects sample rate changes - Recreates resampler as needed - Preserves chunk type (I16/I24/I32/F32/F64) - Quality adapts to bit depth (Medium/High/Very High) ## Architecture PlaylistSource is placed in pmoaudio-ext to avoid circular dependencies: - pmoaudio-ext depends on: pmoaudio, pmoplaylist, pmoaudiocache - No reverse dependencies = clean dependency graph ## Configuration ### pmoaudio-ext/Cargo.toml - Updated 'playlist' feature to include pmoaudiocache, pmocache, pmoflac - Added sources module export ### pmoaudio - Added resampling_node module - Public export: ResamplingNode ## System Requirements ⚠️ **IMPORTANT**: libsoxr-dev must be installed for compilation See INSTALL_NOTES.md for installation instructions per platform. ## Usage Example ```rust // Radio Paradise (homogeneous 44.1kHz/16bit) let mut source = PlaylistSource::new(playlist, cache); let to_i24 = ToI24Node::new(); source.register(Box::new(to_i24)); // Mixed playlist (needs normalization) let mut source = PlaylistSource::new(playlist, cache); let mut resampler = ResamplingNode::new(48000); // Force 48kHz let to_i24 = ToI24Node::new(); source.register(Box::new(resampler)); resampler.register(Box::new(to_i24)); ``` ## Files Changed - pmoaudio-ext/Cargo.toml: Update playlist feature - pmoaudio-ext/src/lib.rs: Add sources module - pmoaudio-ext/src/sources/mod.rs: New sources module - pmoaudio-ext/src/sources/playlist_source.rs: New PlaylistSource (580 lines) - pmoaudio/src/nodes/resampling_node.rs: New ResamplingNode (350 lines) - pmoaudio/src/nodes/mod.rs: Register resampling_node - pmoaudio/src/lib.rs: Export ResamplingNode - INSTALL_NOTES.md: System requirements documentation ## Future Work - GapInsertionNode (inserts silence between tracks) - CrossfadeNode (fade-in/fade-out mixing) - Examples (deferred until implementation validated)
2025-11-05 13:44:24 +00:00
pmocache = { path = "../pmocache", optional = true }
# Async runtime
tokio = { workspace = true }
tokio-util = { version = "0.7" }
async-trait = "0.1"
# Utilities
tracing = "0.1"
Implement complete OGG-FLAC streaming with proper container wrapping This commit implements full OGG container support for FLAC streaming, wrapping FLAC frames in proper OGG pages with CRC32 validation. ## Changes ### pmoaudio-ext/src/sinks/streaming_ogg_flac_sink.rs - Implemented `broadcast_ogg_flac_stream()` with actual OGG wrapping - Added `OggPageWriter` struct for generating OGG pages with proper: - BOS (Beginning of Stream) flag for stream start - EOS (End of Stream) flag for stream end - Page segmentation (255-byte chunks) - CRC32 checksum calculation - Added `read_flac_header()` to extract FLAC header for OGG BOS packet - Added `create_empty_vorbis_comment()` for metadata block - Header caching: BOS + Vorbis Comment pages sent to late-joining clients - Streaming architecture: FLAC frames wrapped in ~4KB OGG pages ### pmoparadise/examples/stream_block.rs - Added dual pipeline support (FLAC + OGG-FLAC) - Added `/test/stream-ogg` endpoint for OGG-FLAC streaming - Updated help messages and documentation - Both pipelines run in parallel with separate sources ### pmoaudio-ext/Cargo.toml - Added `rand = "0.8"` dependency for OGG stream serial generation ## Architecture ``` PCM Input → FLAC Encoder → OGG Wrapper → Broadcast ↓ ↓ ↓ FLAC frames OGG pages HTTP clients ``` ## OGG-FLAC Format 1. BOS page: Contains FLAC identification ("fLaC" + STREAMINFO) 2. Comment page: Contains Vorbis Comment block (metadata) 3. Data pages: Contain FLAC audio frames (~4KB per page) 4. EOS page: Marks end of logical bitstream ## Testing Verified with Radio Paradise streaming: - OGG-FLAC encoder initializes correctly (44100 Hz) - FLAC header extracted (86 bytes) - OGG header cached (176 bytes: BOS + Comment) - Stream generates proper OGG pages (654KB test stream) ## Endpoints - `/test/stream` - Pure FLAC - `/test/stream-ogg` - OGG-FLAC container (NEW) - `/test/stream-icy` - FLAC + ICY metadata - `/test/metadata` - JSON metadata ## TODO (Deferred) OGG chaining on TrackBoundary: Would require encoder restart and new logical bitstream per track. Currently metadata is served via `/test/metadata` endpoint for real-time updates.
2025-11-12 00:26:00 +00:00
rand = "0.8"
# HTTP streaming dependencies
bytes = { version = "1.0", optional = true }
serde = { workspace = true, optional = true }
serde_json = { workspace = true, optional = true }
reqwest = { workspace = true, features = ["stream"], optional = true }
futures = { version = "0.3", optional = true }
ureq = { version = "2", optional = true }
[features]
default = []
cache-sink = ["dep:pmoaudiocache", "dep:pmoflac", "dep:pmometadata", "dep:serde_json"]
playlist = ["cache-sink", "dep:pmoplaylist", "dep:pmocache"]
http-stream = ["dep:pmoflac", "dep:pmometadata", "dep:bytes", "dep:serde", "dep:reqwest", "dep:futures", "dep:ureq"]
all = ["cache-sink", "playlist", "http-stream"]