11// run in release mode
22// `cargo run --release --example mic_playback`
33
4- use web_audio_api:: context:: { AudioContext , AudioContextRegistration , BaseAudioContext } ;
4+ use web_audio_api:: context:: { AudioContext , BaseAudioContext } ;
55use web_audio_api:: media_devices:: { self , MediaStreamConstraints } ;
66use web_audio_api:: node:: BiquadFilterType ;
77use web_audio_api:: node:: {
88 AnalyserNode , AudioBufferSourceNode , AudioNode , AudioScheduledSourceNode , BiquadFilterNode ,
9- ChannelConfig , GainNode , MediaStreamAudioSourceNode ,
9+ GainNode , MediaStreamAudioSourceNode ,
10+ } ;
11+ use web_audio_api:: worklet:: {
12+ AudioParamValues , AudioWorkletGlobalScope , AudioWorkletNode , AudioWorkletNodeOptions ,
13+ AudioWorkletProcessor ,
1014} ;
11- use web_audio_api:: render:: { AudioParamValues , AudioProcessor , AudioRenderQuantum , RenderScope } ;
1215use web_audio_api:: AudioBuffer ;
1316
1417use std:: io:: { stdin, stdout, Write } ;
@@ -30,48 +33,33 @@ const INFO_PANEL_HEIGHT: u16 = 9;
3033const LOG_LEN : usize = 10 ;
3134
3235struct MediaRecorder {
33- /// handle to the audio context, required for all audio nodes
34- registration : AudioContextRegistration ,
35- /// channel configuration (for up/down-mixing of inputs), required for all audio nodes
36- channel_config : ChannelConfig ,
36+ /// handle to the audio node
37+ node : AudioWorkletNode ,
3738 /// receiving end for the samples recorded in the render thread
3839 receiver : Receiver < Vec < Vec < f32 > > > ,
3940}
4041
41- // implement required methods for AudioNode trait
42- impl AudioNode for MediaRecorder {
43- fn registration ( & self ) -> & AudioContextRegistration {
44- & self . registration
45- }
46- fn channel_config ( & self ) -> & ChannelConfig {
47- & self . channel_config
48- }
49- fn number_of_inputs ( & self ) -> usize {
50- 1
51- }
52- fn number_of_outputs ( & self ) -> usize {
53- 0
54- }
55- }
56-
5742impl MediaRecorder {
5843 /// Construct a new MediaRecorder
5944 fn new < C : BaseAudioContext > ( context : & C ) -> Self {
60- context. register ( move |registration| {
61- let ( sender, receiver) = crossbeam_channel:: unbounded ( ) ;
62-
63- // setup the processor, this will run in the render thread
64- let render = MediaRecorderProcessor { sender } ;
45+ let ( sender, receiver) = crossbeam_channel:: unbounded ( ) ;
46+
47+ // setup the processor, this will run in the render thread
48+ let options = AudioWorkletNodeOptions {
49+ number_of_inputs : 1 ,
50+ number_of_outputs : 0 ,
51+ output_channel_count : Default :: default ( ) ,
52+ parameter_data : Default :: default ( ) ,
53+ audio_node_options : Default :: default ( ) ,
54+ processor_options : sender,
55+ } ;
56+ let node = AudioWorkletNode :: new :: < MediaRecorderProcessor > ( context, options) ;
6557
66- // setup the audio node, this will live in the control thread (user facing)
67- let node = MediaRecorder {
68- registration,
69- channel_config : ChannelConfig :: default ( ) ,
70- receiver,
71- } ;
58+ MediaRecorder { node, receiver }
59+ }
7260
73- ( node, Box :: new ( render ) )
74- } )
61+ fn node ( & self ) -> & AudioWorkletNode {
62+ & self . node
7563 }
7664
7765 fn get_data ( self , sample_rate : f32 ) -> Option < AudioBuffer > {
@@ -89,17 +77,23 @@ struct MediaRecorderProcessor {
8977 sender : Sender < Vec < Vec < f32 > > > ,
9078}
9179
92- impl AudioProcessor for MediaRecorderProcessor {
93- fn process (
80+ impl AudioWorkletProcessor for MediaRecorderProcessor {
81+ type ProcessorOptions = Sender < Vec < Vec < f32 > > > ;
82+
83+ fn constructor ( opts : Self :: ProcessorOptions ) -> Self {
84+ Self { sender : opts }
85+ }
86+
87+ fn process < ' a , ' b > (
9488 & mut self ,
95- inputs : & [ AudioRenderQuantum ] ,
96- _outputs : & mut [ AudioRenderQuantum ] ,
97- _params : AudioParamValues < ' _ > ,
98- _scope : & RenderScope ,
89+ inputs : & ' b [ & ' a [ & ' a [ f32 ] ] ] ,
90+ _outputs : & ' b mut [ & ' a mut [ & ' a mut [ f32 ] ] ] ,
91+ _params : AudioParamValues < ' b > ,
92+ _scope : & ' b AudioWorkletGlobalScope ,
9993 ) -> bool {
10094 // single input node
10195 let input = & inputs[ 0 ] ;
102- let data = input. channels ( ) . iter ( ) . map ( |c| c. to_vec ( ) ) . collect ( ) ;
96+ let data = input. iter ( ) . map ( |c| c. to_vec ( ) ) . collect ( ) ;
10397
10498 let _ = self . sender . send ( data) ;
10599
@@ -248,18 +242,19 @@ fn poll_frequency_graph(
248242 . map ( |( i, & f) | ( i as f32 , f) )
249243 . collect ( ) ;
250244
251- let plot = Chart :: new_with_y_range (
245+ let mut chart = Chart :: new_with_y_range (
252246 width as u32 * 2 ,
253247 ( height - 25 ) as u32 * 4 ,
254248 0.0 ,
255249 bin_count as f32 ,
256- -80 .,
250+ -100 .,
257251 20. ,
258- )
259- . lineplot ( & Shape :: Bars ( & points[ ..] ) )
260- . to_string ( ) ;
252+ ) ;
253+ let bars = Shape :: Bars ( & points[ ..] ) ;
254+ let plot = chart. lineplot ( & bars) ;
255+ plot. figures ( ) ;
261256
262- let event = UiEvent :: GraphUpdate ( plot) ;
257+ let event = UiEvent :: GraphUpdate ( plot. to_string ( ) ) ;
263258 let _ = plot_send. send ( event) ; // allowed to fail if the main thread is shutting down
264259 }
265260}
@@ -350,7 +345,7 @@ impl AudioThread {
350345 self . mic_in . disconnect ( ) ;
351346
352347 if beep {
353- let osc = self . context . create_oscillator ( ) ;
348+ let mut osc = self . context . create_oscillator ( ) ;
354349 osc. connect ( & self . context . destination ( ) ) ;
355350 osc. start ( ) ;
356351 osc. stop_at ( self . context . current_time ( ) + 0.2 ) ;
@@ -365,15 +360,15 @@ impl AudioThread {
365360 . take ( )
366361 . and_then ( |r| r. get_data ( self . context . sample_rate ( ) ) ) ;
367362
368- let buffer_source = self . context . create_buffer_source ( ) ;
363+ let mut buffer_source = self . context . create_buffer_source ( ) ;
369364 let playback_rate = Self :: PLAYBACK_STEP . powi ( self . playback_rate_factor ) ;
370365 buffer_source. playback_rate ( ) . set_value ( playback_rate) ;
371366 buffer_source. set_loop ( true ) ;
372367 if let Some ( buf) = buf {
373368 buffer_source. set_buffer ( buf) ;
374369 }
375370
376- let biquad = self . context . create_biquad_filter ( ) ;
371+ let mut biquad = self . context . create_biquad_filter ( ) ;
377372 biquad. set_type ( ( self . biquad_filter_type % 8 ) . into ( ) ) ;
378373
379374 let gain = self . context . create_gain ( ) ;
@@ -396,13 +391,13 @@ impl AudioThread {
396391 self . buffer_source . stop ( ) ;
397392 log:: info!( "Start recording - press space to stop" ) ;
398393
399- let osc = self . context . create_oscillator ( ) ;
394+ let mut osc = self . context . create_oscillator ( ) ;
400395 osc. connect ( & self . context . destination ( ) ) ;
401396 osc. start ( ) ;
402397 osc. stop_at ( self . context . current_time ( ) + 0.2 ) ;
403398
404399 let recorder = MediaRecorder :: new ( & self . context ) ;
405- self . mic_in . connect ( & recorder) ;
400+ self . mic_in . connect ( recorder. node ( ) ) ;
406401 self . mic_in . connect ( & * self . analyser . lock ( ) . unwrap ( ) ) ;
407402
408403 self . recorder = Some ( recorder) ;
0 commit comments