Restructuration de pmoaudio avec ajout des messages de synchro
This commit is contained in:
304
pmoaudio/src/macros.rs
Normal file
304
pmoaudio/src/macros.rs
Normal file
@@ -0,0 +1,304 @@
|
||||
/// 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, I8) => {
|
||||
match $chunk {
|
||||
$crate::AudioChunk::I8(data) => Some(data),
|
||||
_ => None,
|
||||
}
|
||||
};
|
||||
($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::I8($data) => $body,
|
||||
$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::I8($data) => {
|
||||
$crate::AudioChunk::I8($transform)
|
||||
}
|
||||
$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, I8) => {
|
||||
matches!($chunk, $crate::AudioChunk::I8(_))
|
||||
};
|
||||
($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.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.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");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user