284 lines
8.2 KiB
Rust
Executable File
284 lines
8.2 KiB
Rust
Executable File
/// Macros pour simplifier la manipulation des AudioChunk et AudioSegment
|
|
|
|
/// Extrait les données typées d'un AudioChunk
|
|
///
|
|
/// # Exemples
|
|
/// ```
|
|
/// use pmoaudio::{AudioChunk, AudioChunkData, extract_chunk_data};
|
|
///
|
|
/// fn process_i32(chunk: &AudioChunk) {
|
|
/// if let Some(data) = extract_chunk_data!(chunk, I32) {
|
|
/// println!("I32 chunk with {} frames", data.len());
|
|
/// }
|
|
/// }
|
|
/// ```
|
|
#[macro_export]
|
|
macro_rules! extract_chunk_data {
|
|
($chunk:expr, I16) => {
|
|
match $chunk {
|
|
$crate::AudioChunk::I16(data) => Some(data),
|
|
_ => None,
|
|
}
|
|
};
|
|
($chunk:expr, I24) => {
|
|
match $chunk {
|
|
$crate::AudioChunk::I24(data) => Some(data),
|
|
_ => None,
|
|
}
|
|
};
|
|
($chunk:expr, I32) => {
|
|
match $chunk {
|
|
$crate::AudioChunk::I32(data) => Some(data),
|
|
_ => None,
|
|
}
|
|
};
|
|
($chunk:expr, F32) => {
|
|
match $chunk {
|
|
$crate::AudioChunk::F32(data) => Some(data),
|
|
_ => None,
|
|
}
|
|
};
|
|
($chunk:expr, F64) => {
|
|
match $chunk {
|
|
$crate::AudioChunk::F64(data) => Some(data),
|
|
_ => None,
|
|
}
|
|
};
|
|
}
|
|
|
|
/// Match sur le type d'un AudioChunk avec exécution de code pour chaque cas
|
|
///
|
|
/// # Exemples
|
|
/// ```
|
|
/// use pmoaudio::{AudioChunk, match_chunk};
|
|
///
|
|
/// fn print_chunk_info(chunk: &AudioChunk) {
|
|
/// match_chunk!(chunk, data => {
|
|
/// println!("Chunk type: {}, frames: {}", chunk.type_name(), data.len());
|
|
/// });
|
|
/// }
|
|
/// ```
|
|
#[macro_export]
|
|
macro_rules! match_chunk {
|
|
($chunk:expr, $data:ident => $body:expr) => {
|
|
match $chunk {
|
|
$crate::AudioChunk::I16($data) => $body,
|
|
$crate::AudioChunk::I24($data) => $body,
|
|
$crate::AudioChunk::I32($data) => $body,
|
|
$crate::AudioChunk::F32($data) => $body,
|
|
$crate::AudioChunk::F64($data) => $body,
|
|
}
|
|
};
|
|
}
|
|
|
|
/// Map sur un AudioChunk - transforme les données et retourne un nouveau AudioChunk du même type
|
|
///
|
|
/// # Exemples
|
|
/// ```
|
|
/// use pmoaudio::{AudioChunk, map_chunk};
|
|
///
|
|
/// fn add_gain_db(chunk: &AudioChunk, gain_db: f64) -> AudioChunk {
|
|
/// map_chunk!(chunk, data => {
|
|
/// data.set_gain_db(data.gain_db() + gain_db)
|
|
/// })
|
|
/// }
|
|
/// ```
|
|
#[macro_export]
|
|
macro_rules! map_chunk {
|
|
($chunk:expr, $data:ident => $transform:expr) => {
|
|
match $chunk {
|
|
$crate::AudioChunk::I16($data) => $crate::AudioChunk::I16($transform),
|
|
$crate::AudioChunk::I24($data) => $crate::AudioChunk::I24($transform),
|
|
$crate::AudioChunk::I32($data) => $crate::AudioChunk::I32($transform),
|
|
$crate::AudioChunk::F32($data) => $crate::AudioChunk::F32($transform),
|
|
$crate::AudioChunk::F64($data) => $crate::AudioChunk::F64($transform),
|
|
}
|
|
};
|
|
}
|
|
|
|
/// Prédicat sur le type d'un AudioChunk
|
|
///
|
|
/// # Exemples
|
|
/// ```
|
|
/// use pmoaudio::{AudioChunk, is_chunk_type};
|
|
///
|
|
/// fn process_only_i32(chunk: &AudioChunk) {
|
|
/// if is_chunk_type!(chunk, I32) {
|
|
/// println!("Processing I32 chunk");
|
|
/// }
|
|
/// }
|
|
/// ```
|
|
#[macro_export]
|
|
macro_rules! is_chunk_type {
|
|
($chunk:expr, I16) => {
|
|
matches!($chunk, $crate::AudioChunk::I16(_))
|
|
};
|
|
($chunk:expr, I24) => {
|
|
matches!($chunk, $crate::AudioChunk::I24(_))
|
|
};
|
|
($chunk:expr, I32) => {
|
|
matches!($chunk, $crate::AudioChunk::I32(_))
|
|
};
|
|
($chunk:expr, F32) => {
|
|
matches!($chunk, $crate::AudioChunk::F32(_))
|
|
};
|
|
($chunk:expr, F64) => {
|
|
matches!($chunk, $crate::AudioChunk::F64(_))
|
|
};
|
|
}
|
|
|
|
/// Extrait un AudioChunk d'un AudioSegment
|
|
///
|
|
/// # Exemples
|
|
/// ```
|
|
/// use pmoaudio::{AudioSegment, extract_audio_chunk};
|
|
///
|
|
/// fn get_chunk(segment: &AudioSegment) -> Option<&Arc<AudioChunk>> {
|
|
/// extract_audio_chunk!(segment)
|
|
/// }
|
|
/// ```
|
|
#[macro_export]
|
|
macro_rules! extract_audio_chunk {
|
|
($segment:expr) => {
|
|
match &$segment.segment {
|
|
$crate::_AudioSegment::Chunk(chunk) => Some(chunk),
|
|
_ => None,
|
|
}
|
|
};
|
|
}
|
|
|
|
/// Extrait un SyncMarker d'un AudioSegment
|
|
///
|
|
/// # Exemples
|
|
/// ```
|
|
/// use pmoaudio::{AudioSegment, extract_sync_marker};
|
|
///
|
|
/// fn get_marker(segment: &AudioSegment) -> Option<&Arc<SyncMarker>> {
|
|
/// extract_sync_marker!(segment)
|
|
/// }
|
|
/// ```
|
|
#[macro_export]
|
|
macro_rules! extract_sync_marker {
|
|
($segment:expr) => {
|
|
match &$segment.segment {
|
|
$crate::_AudioSegment::Sync(marker) => Some(marker),
|
|
_ => None,
|
|
}
|
|
};
|
|
}
|
|
|
|
/// Match sur le contenu d'un AudioSegment
|
|
///
|
|
/// # Exemples
|
|
/// ```
|
|
/// use pmoaudio::{AudioSegment, match_segment};
|
|
///
|
|
/// fn process_segment(segment: &AudioSegment) {
|
|
/// match_segment!(segment,
|
|
/// chunk => println!("Audio chunk: {}", chunk.type_name()),
|
|
/// marker => println!("Sync marker")
|
|
/// );
|
|
/// }
|
|
/// ```
|
|
#[macro_export]
|
|
macro_rules! match_segment {
|
|
($segment:expr, $chunk_name:ident => $chunk_body:expr, $marker_name:ident => $marker_body:expr) => {
|
|
match &$segment.segment {
|
|
$crate::_AudioSegment::Chunk($chunk_name) => $chunk_body,
|
|
$crate::_AudioSegment::Sync($marker_name) => $marker_body,
|
|
}
|
|
};
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use crate::{AudioChunk, AudioChunkData, AudioSegment, BitDepth};
|
|
|
|
#[test]
|
|
fn test_extract_chunk_data() {
|
|
let data = AudioChunkData::new(vec![[100i32, 200i32]], 44100, 0.0);
|
|
let chunk = AudioChunk::I32(data.clone());
|
|
|
|
// Test extraction réussie
|
|
assert!(extract_chunk_data!(&chunk, I32).is_some());
|
|
assert!(extract_chunk_data!(&chunk, F32).is_none());
|
|
|
|
// Test avec F32
|
|
let f32_chunk = AudioChunk::F32(AudioChunkData::new(vec![[0.5f32, -0.5f32]], 44100, 0.0));
|
|
assert!(extract_chunk_data!(&f32_chunk, F32).is_some());
|
|
assert!(extract_chunk_data!(&f32_chunk, I32).is_none());
|
|
}
|
|
|
|
#[test]
|
|
fn test_match_chunk() {
|
|
let chunk = AudioChunk::I32(AudioChunkData::new(vec![[100i32, 200i32]], 44100, 0.0));
|
|
|
|
let len = match_chunk!(&chunk, data => data.len());
|
|
assert_eq!(len, 1);
|
|
|
|
let sample_rate = match_chunk!(&chunk, data => data.get_sample_rate());
|
|
assert_eq!(sample_rate, 44100);
|
|
}
|
|
|
|
#[test]
|
|
fn test_map_chunk() {
|
|
let chunk = AudioChunk::I32(AudioChunkData::new(vec![[100i32, 200i32]], 44100, 0.0));
|
|
|
|
let modified = map_chunk!(&chunk, data => data.set_gain_db(6.0));
|
|
|
|
match_chunk!(&modified, data => {
|
|
assert_eq!(data.get_gain_db(), 6.0);
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn test_is_chunk_type() {
|
|
let i32_chunk = AudioChunk::I32(AudioChunkData::new(vec![[100i32, 200i32]], 44100, 0.0));
|
|
let f32_chunk = AudioChunk::F32(AudioChunkData::new(vec![[0.5f32, -0.5f32]], 44100, 0.0));
|
|
|
|
assert!(is_chunk_type!(&i32_chunk, I32));
|
|
assert!(!is_chunk_type!(&i32_chunk, F32));
|
|
assert!(is_chunk_type!(&f32_chunk, F32));
|
|
assert!(!is_chunk_type!(&f32_chunk, I32));
|
|
}
|
|
|
|
#[test]
|
|
fn test_extract_audio_chunk() {
|
|
let segment = AudioSegment::new_chunk(0, 0.0, vec![[100i32, 200i32]], 44100, BitDepth::B32);
|
|
|
|
assert!(extract_audio_chunk!(&*segment).is_some());
|
|
|
|
let sync_segment = AudioSegment::new_hearbeat(1, 1.0);
|
|
assert!(extract_audio_chunk!(&*sync_segment).is_none());
|
|
}
|
|
|
|
#[test]
|
|
fn test_extract_sync_marker() {
|
|
let segment = AudioSegment::new_hearbeat(1, 1.0);
|
|
assert!(extract_sync_marker!(&*segment).is_some());
|
|
|
|
let audio_segment =
|
|
AudioSegment::new_chunk(0, 0.0, vec![[100i32, 200i32]], 44100, BitDepth::B32);
|
|
assert!(extract_sync_marker!(&*audio_segment).is_none());
|
|
}
|
|
|
|
#[test]
|
|
fn test_match_segment() {
|
|
let audio_segment =
|
|
AudioSegment::new_chunk(0, 0.0, vec![[100i32, 200i32]], 44100, BitDepth::B32);
|
|
|
|
let result = match_segment!(&*audio_segment,
|
|
chunk => format!("audio: {}", chunk.type_name()),
|
|
_marker => "sync".to_string()
|
|
);
|
|
assert_eq!(result, "audio: i32");
|
|
|
|
let sync_segment = AudioSegment::new_hearbeat(1, 1.0);
|
|
let result = match_segment!(&*sync_segment,
|
|
_chunk => "audio".to_string(),
|
|
_marker => "sync".to_string()
|
|
);
|
|
assert_eq!(result, "sync");
|
|
}
|
|
}
|