codec_core/
lib.rs

1//! # Codec-Core: Audio Codec Library for VoIP
2//!
3//! A simple implementation of G.711 audio codec for VoIP applications.
4//! This library provides ITU-T compliant G.711 μ-law and A-law encoding/decoding
5//! with lookup table optimizations.
6//!
7//! ## Features
8//!
9//! - **ITU-T G.711 Compliant**: Passes official compliance tests
10//! - **Real Audio Tested**: Validated with actual speech samples  
11//! - **Good Quality**: ~37 dB SNR with real speech
12//! - **Lookup Table Optimized**: Fast O(1) encoding/decoding
13//!
14//! ## Implementation
15//!
16//! - **Lookup Tables**: Pre-computed tables for O(1) operations
17//! - **Simple APIs**: Straightforward encoding/decoding functions
18//!
19//! ## Usage
20//!
21//! ### Quick Start
22//!
23//! ```rust
24//! use codec_core::codecs::g711::G711Codec;
25//! use codec_core::types::{AudioCodec, CodecConfig, CodecType, SampleRate};
26//!
27//! // Create a G.711 μ-law codec
28//! let config = CodecConfig::new(CodecType::G711Pcmu)
29//!     .with_sample_rate(SampleRate::Rate8000)
30//!     .with_channels(1);
31//! let mut codec = G711Codec::new_pcmu(config)?;
32//!
33//! // Encode audio samples (20ms at 8kHz = 160 samples)
34//! let samples = vec![0i16; 160];
35//! let encoded = codec.encode(&samples)?;
36//!
37//! // Decode back to samples
38//! let decoded = codec.decode(&encoded)?;
39//! # Ok::<(), Box<dyn std::error::Error>>(())
40//! ```
41//!
42//! ## Testing & Validation
43//!
44//! The library includes comprehensive testing including real audio validation:
45//!
46//! ```bash
47//! # Run all codec tests including WAV roundtrip tests
48//! cargo test
49//!
50//! # Run only G.711 WAV roundtrip tests (downloads real speech audio)
51//! cargo test wav_roundtrip_test -- --nocapture
52//! ```
53//!
54//! The WAV roundtrip tests automatically download real speech samples and validate:
55//! - Signal-to-Noise Ratio (SNR) measurement
56//! - Round-trip audio quality preservation  
57//! - Proper encoding/decoding with real audio data
58//! - Output WAV files for manual quality assessment
59//!
60//! ## Error Handling
61//!
62//! All codec operations return `Result` types with detailed error information:
63//!
64//! ```rust
65//! use codec_core::codecs::g711::G711Codec;
66//! use codec_core::types::{CodecConfig, CodecType, SampleRate};
67//! use codec_core::error::CodecError;
68//!
69//! // Handle configuration errors
70//! let config = CodecConfig::new(CodecType::G711Pcmu)
71//!     .with_sample_rate(SampleRate::Rate48000) // Invalid for G.711
72//!     .with_channels(1);
73//!
74//! match G711Codec::new_pcmu(config) {
75//!     Ok(codec) => println!("Codec created successfully"),
76//!     Err(CodecError::InvalidSampleRate { rate, supported }) => {
77//!         println!("Invalid sample rate {}, supported: {:?}", rate, supported);
78//!     }
79//!     Err(e) => println!("Other error: {}", e),
80//! }
81//! ```
82//!
83//! ## Performance Tips
84//!
85
86//! - Use appropriate frame sizes (160 samples for G.711 at 8kHz/20ms)
87//!
88//! ### Direct G.711 Functions
89//!
90//! ```rust
91//! use codec_core::codecs::g711::{alaw_compress, alaw_expand, ulaw_compress, ulaw_expand};
92//!
93//! // Single sample processing
94//! let sample = 1024i16;
95//! let alaw_encoded = alaw_compress(sample);
96//! let alaw_decoded = alaw_expand(alaw_encoded);
97//!
98//! let ulaw_encoded = ulaw_compress(sample);
99//! let ulaw_decoded = ulaw_expand(ulaw_encoded);
100//! ```
101//!
102//! ### Frame-Based Processing
103//!
104//! ```rust
105//! use codec_core::codecs::g711::{G711Codec, G711Variant};
106//!
107//! let mut codec = G711Codec::new(G711Variant::MuLaw);
108//!
109//! // Process 160 samples (20ms at 8kHz)
110//! let input_frame = vec![1000i16; 160]; // Some test samples
111//! let encoded = codec.compress(&input_frame).unwrap();
112//!
113//! // Decode back to samples (same count for G.711)
114//! let decoded = codec.expand(&encoded).unwrap();
115//! assert_eq!(input_frame.len(), decoded.len());
116//! # Ok::<(), Box<dyn std::error::Error>>(())
117//! ```
118//!
119//! ## Supported Codecs
120//!
121//! | Codec | Sample Rate | Channels | Bitrate | Frame Size | Status |
122//! |-------|-------------|----------|---------|------------|--------|
123//! | **G.711 μ-law (PCMU)** | 8 kHz | 1 | 64 kbps | 160 samples | ✅ Production |
124//! | **G.711 A-law (PCMA)** | 8 kHz | 1 | 64 kbps | 160 samples | ✅ Production |
125//!
126//! ## Quality Metrics
127//!
128//! Based on real audio testing with the included WAV roundtrip tests:
129//!
130//! - **G.711**: 37+ dB SNR (excellent quality, industry standard)
131//!
132//! ## Feature Flags
133//!
134//! ### Core Codecs (enabled by default)
135//! - `g711`: G.711 μ-law/A-law codecs
136
137#![deny(missing_docs)]
138#![warn(clippy::all)]
139#![warn(clippy::pedantic)]
140#![warn(clippy::nursery)]
141#![allow(clippy::module_name_repetitions)]
142
143pub mod codecs;
144pub mod error;
145pub mod types;
146pub mod utils;
147
148// Re-export commonly used types and traits
149pub use codecs::{CodecFactory, CodecRegistry};
150pub use error::{CodecError, Result};
151pub use types::{
152    AudioCodec, AudioFrame, CodecCapability, CodecConfig, CodecInfo, CodecType, SampleRate,
153};
154
155/// Version information for the codec library
156pub const VERSION: &str = env!("CARGO_PKG_VERSION");
157
158/// Supported codec types
159pub const SUPPORTED_CODECS: &[&str] = &[
160    #[cfg(feature = "g711")]
161    "PCMU",
162    #[cfg(feature = "g711")]
163    "PCMA",
164
165];
166
167/// Initialize the codec library
168///
169/// This function should be called once at program startup to initialize
170/// any global state or lookup tables. It's safe to call multiple times.
171///
172/// # Errors
173///
174/// Returns an error if initialization fails (e.g., SIMD detection fails)
175pub fn init() -> Result<()> {
176    // Initialize logging if not already done
177    let _ = tracing_subscriber::fmt::try_init();
178
179
180
181    // Initialize lookup tables
182    #[cfg(feature = "g711")]
183    codecs::g711::init_tables();
184
185    tracing::info!("Codec-Core v{} initialized", VERSION);
186    tracing::info!("Supported codecs: {:?}", SUPPORTED_CODECS);
187
188    Ok(())
189}
190
191/// Get library information
192pub fn info() -> LibraryInfo {
193    LibraryInfo {
194        version: VERSION,
195        supported_codecs: SUPPORTED_CODECS.to_vec(),
196    }
197}
198
199/// Library information structure
200#[derive(Debug, Clone)]
201pub struct LibraryInfo {
202    /// Library version
203    pub version: &'static str,
204    /// List of supported codec names
205    pub supported_codecs: Vec<&'static str>,
206}
207
208#[cfg(test)]
209mod tests {
210    use super::*;
211
212    #[test]
213    fn test_init() {
214        assert!(init().is_ok());
215    }
216
217    #[test]
218    fn test_info() {
219        let info = info();
220        assert_eq!(info.version, VERSION);
221        assert!(!info.supported_codecs.is_empty());
222    }
223
224    #[test]
225    fn test_supported_codecs() {
226        assert!(!SUPPORTED_CODECS.is_empty());
227        
228        #[cfg(feature = "g711")]
229        {
230            assert!(SUPPORTED_CODECS.contains(&"PCMU"));
231            assert!(SUPPORTED_CODECS.contains(&"PCMA"));
232        }
233        
234        #[cfg(feature = "g722")]
235        // G.722 support removed - only G.711 variants now supported
236        
237        #[cfg(any(feature = "g729", feature = "g729-sim"))]
238        assert!(SUPPORTED_CODECS.contains(&"G729"));
239        
240        #[cfg(any(feature = "opus", feature = "opus-sim"))]
241        assert!(SUPPORTED_CODECS.contains(&"opus"));
242    }
243}