1use crate::buffer::{AudioBuffer, AudioBufferOptions};
4use crate::context::{
5    AudioContextRegistration, AudioContextState, AudioParamId, ConcreteBaseAudioContext,
6    DESTINATION_NODE_ID,
7};
8use crate::decoding::MediaDecoder;
9use crate::events::{Event, EventHandler, EventType};
10use crate::node::{AudioNode, AudioNodeOptions};
11use crate::param::AudioParamDescriptor;
12use crate::periodic_wave::{PeriodicWave, PeriodicWaveOptions};
13use crate::{node, AudioListener};
14
15use std::future::Future;
16
17#[allow(clippy::module_name_repetitions)]
23pub trait BaseAudioContext {
24    #[doc(hidden)] fn base(&self) -> &ConcreteBaseAudioContext;
27
28    fn decode_audio_data_sync<R: std::io::Read + Send + Sync + 'static>(
67        &self,
68        input: R,
69    ) -> Result<AudioBuffer, Box<dyn std::error::Error + Send + Sync>> {
70        let mut buffer = MediaDecoder::try_new(input)?
72            .collect::<Result<Vec<_>, _>>()?
73            .into_iter()
74            .reduce(|mut accum, item| {
75                accum.extend(&item);
76                accum
77            })
78            .unwrap_or_else(|| AudioBuffer::from(vec![vec![]], self.sample_rate()));
80
81        buffer.resample(self.sample_rate());
83
84        Ok(buffer)
85    }
86
87    fn decode_audio_data<R: std::io::Read + Send + Sync + 'static>(
106        &self,
107        input: R,
108    ) -> impl Future<Output = Result<AudioBuffer, Box<dyn std::error::Error + Send + Sync>>>
109           + Send
110           + 'static {
111        let sample_rate = self.sample_rate();
112        async move {
113            let mut buffer = MediaDecoder::try_new(input)?
115                .collect::<Result<Vec<_>, _>>()?
116                .into_iter()
117                .reduce(|mut accum, item| {
118                    accum.extend(&item);
119                    accum
120                })
121                .unwrap_or_else(|| AudioBuffer::from(vec![vec![]], sample_rate));
123
124            buffer.resample(sample_rate);
126
127            Ok(buffer)
128        }
129    }
130
131    #[must_use]
137    fn create_buffer(
138        &self,
139        number_of_channels: usize,
140        length: usize,
141        sample_rate: f32,
142    ) -> AudioBuffer {
143        let options = AudioBufferOptions {
144            number_of_channels,
145            length,
146            sample_rate,
147        };
148
149        AudioBuffer::new(options)
150    }
151
152    #[must_use]
154    fn create_analyser(&self) -> node::AnalyserNode {
155        node::AnalyserNode::new(self.base(), node::AnalyserOptions::default())
156    }
157
158    #[must_use]
160    fn create_biquad_filter(&self) -> node::BiquadFilterNode {
161        node::BiquadFilterNode::new(self.base(), node::BiquadFilterOptions::default())
162    }
163
164    #[must_use]
166    fn create_buffer_source(&self) -> node::AudioBufferSourceNode {
167        node::AudioBufferSourceNode::new(self.base(), node::AudioBufferSourceOptions::default())
168    }
169
170    #[must_use]
172    fn create_constant_source(&self) -> node::ConstantSourceNode {
173        node::ConstantSourceNode::new(self.base(), node::ConstantSourceOptions::default())
174    }
175
176    #[must_use]
178    fn create_convolver(&self) -> node::ConvolverNode {
179        node::ConvolverNode::new(self.base(), node::ConvolverOptions::default())
180    }
181
182    #[must_use]
184    fn create_channel_merger(&self, number_of_inputs: usize) -> node::ChannelMergerNode {
185        let opts = node::ChannelMergerOptions {
186            number_of_inputs,
187            ..node::ChannelMergerOptions::default()
188        };
189        node::ChannelMergerNode::new(self.base(), opts)
190    }
191
192    #[must_use]
194    fn create_channel_splitter(&self, number_of_outputs: usize) -> node::ChannelSplitterNode {
195        let opts = node::ChannelSplitterOptions {
196            number_of_outputs,
197            ..node::ChannelSplitterOptions::default()
198        };
199        node::ChannelSplitterNode::new(self.base(), opts)
200    }
201
202    #[must_use]
204    fn create_delay(&self, max_delay_time: f64) -> node::DelayNode {
205        let opts = node::DelayOptions {
206            max_delay_time,
207            ..node::DelayOptions::default()
208        };
209        node::DelayNode::new(self.base(), opts)
210    }
211
212    #[must_use]
214    fn create_dynamics_compressor(&self) -> node::DynamicsCompressorNode {
215        node::DynamicsCompressorNode::new(self.base(), node::DynamicsCompressorOptions::default())
216    }
217
218    #[must_use]
220    fn create_gain(&self) -> node::GainNode {
221        node::GainNode::new(self.base(), node::GainOptions::default())
222    }
223
224    #[must_use]
233    fn create_iir_filter(&self, feedforward: Vec<f64>, feedback: Vec<f64>) -> node::IIRFilterNode {
234        let options = node::IIRFilterOptions {
235            audio_node_options: AudioNodeOptions::default(),
236            feedforward,
237            feedback,
238        };
239        node::IIRFilterNode::new(self.base(), options)
240    }
241
242    #[must_use]
244    fn create_oscillator(&self) -> node::OscillatorNode {
245        node::OscillatorNode::new(self.base(), node::OscillatorOptions::default())
246    }
247
248    #[must_use]
250    fn create_panner(&self) -> node::PannerNode {
251        node::PannerNode::new(self.base(), node::PannerOptions::default())
252    }
253
254    #[must_use]
259    fn create_periodic_wave(&self, options: PeriodicWaveOptions) -> PeriodicWave {
260        PeriodicWave::new(self.base(), options)
261    }
262
263    #[must_use]
272    fn create_script_processor(
273        &self,
274        buffer_size: usize,
275        number_of_input_channels: usize,
276        number_of_output_channels: usize,
277    ) -> node::ScriptProcessorNode {
278        let options = node::ScriptProcessorOptions {
279            buffer_size,
280            number_of_input_channels,
281            number_of_output_channels,
282        };
283
284        node::ScriptProcessorNode::new(self.base(), options)
285    }
286
287    #[must_use]
289    fn create_stereo_panner(&self) -> node::StereoPannerNode {
290        node::StereoPannerNode::new(self.base(), node::StereoPannerOptions::default())
291    }
292
293    #[must_use]
295    fn create_wave_shaper(&self) -> node::WaveShaperNode {
296        node::WaveShaperNode::new(self.base(), node::WaveShaperOptions::default())
297    }
298
299    #[must_use]
302    fn destination(&self) -> node::AudioDestinationNode {
303        let registration = AudioContextRegistration {
304            id: DESTINATION_NODE_ID,
305            context: self.base().clone(),
306        };
307        let channel_config = self.base().destination_channel_config();
308        node::AudioDestinationNode::from_raw_parts(registration, channel_config)
309    }
310
311    #[must_use]
313    fn listener(&self) -> AudioListener {
314        self.base().listener()
315    }
316
317    #[must_use]
319    fn sample_rate(&self) -> f32 {
320        self.base().sample_rate()
321    }
322
323    #[must_use]
325    fn state(&self) -> AudioContextState {
326        self.base().state()
327    }
328
329    #[must_use]
332    fn current_time(&self) -> f64 {
333        self.base().current_time()
334    }
335
336    #[must_use]
340    fn create_audio_param(
341        &self,
342        opts: AudioParamDescriptor,
343        dest: &AudioContextRegistration,
344    ) -> (crate::param::AudioParam, AudioParamId) {
345        let param = self.base().register(move |registration| {
346            let (node, proc) = crate::param::audio_param_pair(opts, registration);
347
348            (node, Box::new(proc))
349        });
350
351        self.base().queue_audio_param_connect(¶m, dest.id());
353
354        let proc_id = AudioParamId(param.registration().id().0);
355        (param, proc_id)
356    }
357
358    fn set_onstatechange<F: FnMut(Event) + Send + 'static>(&self, mut callback: F) {
363        let callback = move |_| {
364            callback(Event {
365                type_: "statechange",
366            })
367        };
368
369        self.base().set_event_handler(
370            EventType::StateChange,
371            EventHandler::Multiple(Box::new(callback)),
372        );
373    }
374
375    fn clear_onstatechange(&self) {
377        self.base().clear_event_handler(EventType::StateChange);
378    }
379
380    #[cfg(test)]
381    fn mock_registration(&self) -> AudioContextRegistration {
382        AudioContextRegistration {
383            id: crate::context::AudioNodeId(0),
384            context: self.base().clone(),
385        }
386    }
387}
388
389#[cfg(test)]
390mod tests {
391    use super::*;
392    use crate::context::OfflineAudioContext;
393
394    use float_eq::assert_float_eq;
395
396    fn require_send_sync_static<T: Send + Sync + 'static>(_: T) {}
397
398    #[test]
399    fn test_decode_audio_data_sync() {
400        let context = OfflineAudioContext::new(1, 1, 44100.);
401        let file = std::fs::File::open("samples/sample.wav").unwrap();
402        let audio_buffer = context.decode_audio_data_sync(file).unwrap();
403
404        assert_eq!(audio_buffer.sample_rate(), 44100.);
405        assert_eq!(audio_buffer.length(), 142_187);
406        assert_eq!(audio_buffer.number_of_channels(), 2);
407        assert_float_eq!(audio_buffer.duration(), 3.224, abs_all <= 0.001);
408
409        let left_start = &audio_buffer.get_channel_data(0)[0..100];
410        let right_start = &audio_buffer.get_channel_data(1)[0..100];
411        assert!(left_start != right_start);
413    }
414
415    #[test]
416    fn test_decode_audio_data_future_send_static() {
417        let context = OfflineAudioContext::new(1, 1, 44100.);
418        let file = std::fs::File::open("samples/sample.wav").unwrap();
419        let future = context.decode_audio_data(file);
420        require_send_sync_static(future);
421    }
422
423    #[test]
424    fn test_decode_audio_data_async() {
425        use futures::executor;
426        let context = OfflineAudioContext::new(1, 1, 44100.);
427        let file = std::fs::File::open("samples/sample.wav").unwrap();
428        let future = context.decode_audio_data(file);
429        let audio_buffer = executor::block_on(future).unwrap();
430
431        assert_eq!(audio_buffer.sample_rate(), 44100.);
432        assert_eq!(audio_buffer.length(), 142_187);
433        assert_eq!(audio_buffer.number_of_channels(), 2);
434        assert_float_eq!(audio_buffer.duration(), 3.224, abs_all <= 0.001);
435
436        let left_start = &audio_buffer.get_channel_data(0)[0..100];
437        let right_start = &audio_buffer.get_channel_data(1)[0..100];
438        assert!(left_start != right_start);
440    }
441
442    #[allow(dead_code)]
445    fn test_decode_audio_data_empty() {
446        let context = OfflineAudioContext::new(1, 1, 44100.);
447        let file = std::fs::File::open("samples/empty_2c.wav").unwrap();
448        let audio_buffer = context.decode_audio_data_sync(file).unwrap();
449        assert_eq!(audio_buffer.length(), 0);
450    }
451
452    #[test]
453    fn test_decode_audio_data_decoding_error() {
454        let context = OfflineAudioContext::new(1, 1, 44100.);
455        let file = std::fs::File::open("samples/corrupt.wav").unwrap();
456        assert!(context.decode_audio_data_sync(file).is_err());
457    }
458
459    #[test]
460    fn test_create_buffer() {
461        let number_of_channels = 3;
462        let length = 2000;
463        let sample_rate = 96_000.;
464
465        let context = OfflineAudioContext::new(1, 1, 44100.);
466        let buffer = context.create_buffer(number_of_channels, length, sample_rate);
467
468        assert_eq!(buffer.number_of_channels(), 3);
469        assert_eq!(buffer.length(), 2000);
470        assert_float_eq!(buffer.sample_rate(), 96000., abs_all <= 0.);
471    }
472}