audio_lab/signal/fs/
npy.rs1use crate::signal::{FreqSignal, SignalError, TimeSignal};
2
3#[derive(Debug, thiserror::Error)]
4pub enum NpyOrSignalError {
5 #[error(transparent)]
6 Npy(#[from] ndarray_npy::ReadNpyError),
7 #[error(transparent)]
8 Signal(#[from] SignalError),
9}
10
11pub fn read_npy_time(
12 path: impl AsRef<std::path::Path>,
13 sample_rate: f64,
14) -> Result<TimeSignal, NpyOrSignalError> {
15 let y_data = ndarray_npy::read_npy(path).map_err(NpyOrSignalError::Npy)?;
16 TimeSignal::new(y_data, sample_rate).map_err(NpyOrSignalError::Signal)
17}
18
19pub fn write_npy_time(
20 signal: &TimeSignal,
21 path: impl AsRef<std::path::Path>,
22) -> Result<(), ndarray_npy::WriteNpyError> {
23 ndarray_npy::write_npy(path, &signal.time_data().to_owned())
24}
25
26pub fn read_npy_freq(
27 path: impl AsRef<std::path::Path>,
28 sample_rate: f64,
29 num_time_steps: Option<usize>,
30) -> Result<FreqSignal, NpyOrSignalError> {
31 let y_data = ndarray_npy::read_npy(path).map_err(NpyOrSignalError::Npy)?;
32 FreqSignal::new(y_data, sample_rate, num_time_steps).map_err(NpyOrSignalError::Signal)
33}
34
35pub fn write_npy_freq(
36 signal: &FreqSignal,
37 path: impl AsRef<std::path::Path>,
38) -> Result<(), ndarray_npy::WriteNpyError> {
39 ndarray_npy::write_npy(path, &signal.freq_data().to_owned())
40}
41
42#[cfg(test)]
43mod tests {
44 use std::time::{SystemTime, UNIX_EPOCH};
45
46 use ndarray::arr2;
47 use num::complex::Complex64;
48
49 use super::*;
50
51 #[test]
52 fn writes_and_reads_time_signal_npy() {
53 let signal = TimeSignal::new(arr2(&[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]), 44_100.0).unwrap();
54 let path = std::env::temp_dir().join(format!(
55 "audio-lab-{}-{}.npy",
56 std::process::id(),
57 SystemTime::now()
58 .duration_since(UNIX_EPOCH)
59 .unwrap()
60 .as_nanos()
61 ));
62
63 write_npy_time(&signal, &path).unwrap();
64 let loaded = read_npy_time(&path, 44_100.0).unwrap();
65 std::fs::remove_file(&path).unwrap();
66
67 assert_eq!(loaded, signal);
68 }
69
70 #[test]
71 fn writes_and_reads_freq_signal_npy() {
72 let signal = FreqSignal::new(
73 arr2(&[
74 [Complex64::new(1.0, 2.0), Complex64::new(3.0, 4.0)],
75 [Complex64::new(5.0, 6.0), Complex64::new(7.0, 8.0)],
76 ]),
77 44_100.0,
78 Some(3),
79 )
80 .unwrap();
81 let path = std::env::temp_dir().join(format!(
82 "audio-lab-freq-{}-{}.npy",
83 std::process::id(),
84 SystemTime::now()
85 .duration_since(UNIX_EPOCH)
86 .unwrap()
87 .as_nanos()
88 ));
89
90 write_npy_freq(&signal, &path).unwrap();
91 let loaded = read_npy_freq(&path, 44_100.0, Some(3)).unwrap();
92 std::fs::remove_file(&path).unwrap();
93
94 assert_eq!(loaded, signal);
95 }
96}