rust_audio_api/nodes/
file.rs1use crate::nodes::resampler::{ResamplerState, RingIter};
2use crate::types::{AUDIO_UNIT_SIZE, AudioUnit};
3use dasp::signal::Signal;
4use ringbuf::HeapRb;
5use ringbuf::traits::{Observer, Producer, Split};
6use std::sync::Arc;
7use std::sync::atomic::{AtomicBool, Ordering};
8use std::thread;
9use std::time::Duration;
10use symphonia::core::audio::SampleBuffer;
11use symphonia::core::codecs::DecoderOptions;
12use symphonia::core::formats::FormatOptions;
13use symphonia::core::io::MediaSourceStream;
14use symphonia::core::meta::MetadataOptions;
15use symphonia::core::probe::Hint;
16
17pub struct FileNode {
37 resampler: ResamplerState,
38 gain: f32,
39 _running: Arc<AtomicBool>,
40}
41
42impl FileNode {
43 pub fn new(file_path: &str, target_sample_rate: u32) -> Result<Self, anyhow::Error> {
49 let file = std::fs::File::open(file_path)?;
50 let mss = MediaSourceStream::new(Box::new(file), Default::default());
51
52 let hint = Hint::new();
53 let format_opts = FormatOptions::default();
54 let metadata_opts = MetadataOptions::default();
55 let decoder_opts = DecoderOptions::default();
56
57 let probed =
58 symphonia::default::get_probe().format(&hint, mss, &format_opts, &metadata_opts)?;
59
60 let mut format = probed.format;
61
62 let track = format
63 .tracks()
64 .iter()
65 .find(|t| t.codec_params.codec != symphonia::core::codecs::CODEC_TYPE_NULL)
66 .cloned()
67 .ok_or_else(|| anyhow::anyhow!("No audio track found"))?;
68
69 let track_id = track.id;
70 let mut decoder =
71 symphonia::default::get_codecs().make(&track.codec_params, &decoder_opts)?;
72
73 let channels = track.codec_params.channels.unwrap_or_default().count();
74 let sample_rate = track.codec_params.sample_rate.unwrap_or(target_sample_rate);
75
76 println!("Audio file sample rate: {:?}", sample_rate);
77
78 let capacity = sample_rate as usize * channels * 2;
80 let ringbuf = HeapRb::<f32>::new(capacity);
81 let (mut producer, consumer) = ringbuf.split();
82
83 let running = Arc::new(AtomicBool::new(true));
84 let running_clone = running.clone();
85
86 thread::spawn(move || {
87 let mut sample_buf = None;
88
89 while running_clone.load(Ordering::Relaxed) {
90 if producer.is_full() {
91 thread::sleep(Duration::from_millis(10));
92 continue;
93 }
94
95 let packet = match format.next_packet() {
96 Ok(p) => p,
97 Err(_) => break, };
99
100 if packet.track_id() != track_id {
101 continue;
102 }
103
104 let decoded = match decoder.decode(&packet) {
105 Ok(d) => d,
106 Err(_) => continue,
107 };
108
109 if sample_buf.is_none() {
110 let spec = *decoded.spec();
111 let duration = decoded.capacity() as u64;
112 sample_buf = Some(SampleBuffer::<f32>::new(duration, spec));
113 }
114
115 let buf = sample_buf.as_mut().unwrap();
116 buf.copy_interleaved_ref(decoded);
117
118 let samples = buf.samples();
119
120 for &sample in samples {
121 if !running_clone.load(Ordering::Relaxed) {
122 break;
123 }
124 while producer.is_full() && running_clone.load(Ordering::Relaxed) {
125 thread::sleep(Duration::from_millis(1));
126 }
127 let _ = producer.try_push(sample);
128 }
129 }
130 });
131
132 let ring_iter = RingIter { consumer, channels };
133
134 let resampler = if sample_rate != target_sample_rate {
135 let ring_buffer = dasp::ring_buffer::Fixed::from([[0.0; 2]; AUDIO_UNIT_SIZE]);
136 let sinc = dasp::interpolate::sinc::Sinc::new(ring_buffer);
137 let converter =
138 ring_iter.from_hz_to_hz(sinc, sample_rate as f64, target_sample_rate as f64);
139 ResamplerState::Resampling(Box::new(converter))
140 } else {
141 ResamplerState::Passthrough(ring_iter)
142 };
143
144 Ok(Self {
145 resampler,
146 gain: 1.0,
147 _running: running,
148 })
149 }
150
151 pub fn set_gain(&mut self, gain: f32) {
153 self.gain = gain;
154 }
155
156 #[inline(always)]
157 pub fn process(&mut self, _input: Option<&AudioUnit>, output: &mut AudioUnit) {
158 match &mut self.resampler {
159 ResamplerState::Passthrough(iter) => {
160 for out in output.iter_mut().take(AUDIO_UNIT_SIZE) {
161 *out = iter.next();
162 }
163 }
164 ResamplerState::Resampling(converter) => {
165 for out in output.iter_mut().take(AUDIO_UNIT_SIZE) {
166 *out = converter.next();
167 }
168 }
169 }
170
171 dasp::slice::map_in_place(&mut output[..], |frame| {
173 [frame[0] * self.gain, frame[1] * self.gain]
174 });
175 }
176}
177
178impl Drop for FileNode {
179 fn drop(&mut self) {
180 self._running.store(false, Ordering::Relaxed);
181 }
182}