1+ #[ cfg( feature = "iai" ) ]  
12use  iai:: black_box; 
23
4+ #[ cfg( not( feature = "iai" ) ) ]  
5+ use  criterion:: { black_box,  criterion_group,  criterion_main,  Criterion } ; 
6+ 
37use  web_audio_api:: context:: BaseAudioContext ; 
48use  web_audio_api:: context:: OfflineAudioContext ; 
59use  web_audio_api:: node:: { AudioNode ,  AudioScheduledSourceNode ,  PanningModelType } ; 
10+ use  web_audio_api:: AudioBuffer ; 
11+ 
12+ use  std:: fs:: File ; 
13+ use  std:: sync:: OnceLock ; 
614
715const  SAMPLE_RATE :  f32  = 48000. ; 
816const  DURATION :  usize  = 10 ; 
917const  SAMPLES :  usize  = SAMPLE_RATE  as  usize  *  DURATION ; 
18+ const  SAMPLES_SHORT :  usize  = SAMPLE_RATE  as  usize ;  // only 1 second for heavy benchmarks 
19+ 
20+ /// Load an audio buffer and cache the result 
21+ /// 
22+ /// We don't want to measure the IO and decoding in most of our benchmarks, so by using this static 
23+ /// instance we avoid this in the criterion benchmarks because the file is already loaded in the 
24+ /// warmup phase. 
25+ fn  get_audio_buffer ( ctx :  & OfflineAudioContext )  -> AudioBuffer  { 
26+     static  BUFFER :  OnceLock < AudioBuffer >  = OnceLock :: new ( ) ; 
27+     BUFFER 
28+         . get_or_init ( || { 
29+             let  file = File :: open ( "samples/think-stereo-48000.wav" ) . unwrap ( ) ; 
30+             ctx. decode_audio_data_sync ( file) . unwrap ( ) 
31+         } ) 
32+         . clone ( ) 
33+ } 
1034
1135pub  fn  bench_ctor ( )  { 
1236    let  ctx = OfflineAudioContext :: new ( 2 ,  black_box ( SAMPLES ) ,  SAMPLE_RATE ) ; 
1337    assert_eq ! ( ctx. start_rendering_sync( ) . length( ) ,  SAMPLES ) ; 
1438} 
1539
40+ // This benchmark only makes sense in `iai`, because subsequent runs use the cached audiobuffer. 
41+ // However we would like to run this test here so the cache is filled for the subsequent benches. 
42+ pub  fn  bench_audio_buffer_decode ( )  { 
43+     let  ctx = OfflineAudioContext :: new ( 2 ,  black_box ( SAMPLES ) ,  SAMPLE_RATE ) ; 
44+     let  buffer = get_audio_buffer ( & ctx) ; 
45+     assert_eq ! ( buffer. length( ) ,  101129 ) ; 
46+ } 
47+ 
1648pub  fn  bench_sine ( )  { 
1749    let  ctx = OfflineAudioContext :: new ( 2 ,  black_box ( SAMPLES ) ,  SAMPLE_RATE ) ; 
1850    let  mut  osc = ctx. create_oscillator ( ) ; 
@@ -56,9 +88,7 @@ pub fn bench_sine_gain_delay() {
5688
5789pub  fn  bench_buffer_src ( )  { 
5890    let  ctx = OfflineAudioContext :: new ( 2 ,  black_box ( SAMPLES ) ,  SAMPLE_RATE ) ; 
59- 
60-     let  file = std:: fs:: File :: open ( "samples/think-stereo-48000.wav" ) . unwrap ( ) ; 
61-     let  buffer = ctx. decode_audio_data_sync ( file) . unwrap ( ) ; 
91+     let  buffer = get_audio_buffer ( & ctx) ; 
6292
6393    let  mut  src = ctx. create_buffer_source ( ) ; 
6494    src. connect ( & ctx. destination ( ) ) ; 
@@ -70,9 +100,7 @@ pub fn bench_buffer_src() {
70100
71101pub  fn  bench_buffer_src_delay ( )  { 
72102    let  ctx = OfflineAudioContext :: new ( 2 ,  black_box ( SAMPLES ) ,  SAMPLE_RATE ) ; 
73- 
74-     let  file = std:: fs:: File :: open ( "samples/think-stereo-48000.wav" ) . unwrap ( ) ; 
75-     let  buffer = ctx. decode_audio_data_sync ( file) . unwrap ( ) ; 
103+     let  buffer = get_audio_buffer ( & ctx) ; 
76104
77105    let  delay = ctx. create_delay ( 0.3 ) ; 
78106    delay. delay_time ( ) . set_value ( 0.2 ) ; 
@@ -89,8 +117,7 @@ pub fn bench_buffer_src_delay() {
89117
90118pub  fn  bench_buffer_src_iir ( )  { 
91119    let  ctx = OfflineAudioContext :: new ( 2 ,  black_box ( SAMPLES ) ,  SAMPLE_RATE ) ; 
92-     let  file = std:: fs:: File :: open ( "samples/think-stereo-48000.wav" ) . unwrap ( ) ; 
93-     let  buffer = ctx. decode_audio_data_sync ( file) . unwrap ( ) ; 
120+     let  buffer = get_audio_buffer ( & ctx) ; 
94121
95122    // these values correspond to a lowpass filter at 200Hz (calculated from biquad) 
96123    let  feedforward = vec ! [ 
@@ -116,8 +143,7 @@ pub fn bench_buffer_src_iir() {
116143
117144pub  fn  bench_buffer_src_biquad ( )  { 
118145    let  ctx = OfflineAudioContext :: new ( 2 ,  black_box ( SAMPLES ) ,  SAMPLE_RATE ) ; 
119-     let  file = std:: fs:: File :: open ( "samples/think-stereo-48000.wav" ) . unwrap ( ) ; 
120-     let  buffer = ctx. decode_audio_data_sync ( file) . unwrap ( ) ; 
146+     let  buffer = get_audio_buffer ( & ctx) ; 
121147
122148    // Create an biquad filter node (defaults to low pass) 
123149    let  biquad = ctx. create_biquad_filter ( ) ; 
@@ -135,8 +161,7 @@ pub fn bench_buffer_src_biquad() {
135161
136162pub  fn  bench_stereo_positional ( )  { 
137163    let  ctx = OfflineAudioContext :: new ( 2 ,  black_box ( SAMPLES ) ,  SAMPLE_RATE ) ; 
138-     let  file = std:: fs:: File :: open ( "samples/think-stereo-48000.wav" ) . unwrap ( ) ; 
139-     let  buffer = ctx. decode_audio_data_sync ( file) . unwrap ( ) ; 
164+     let  buffer = get_audio_buffer ( & ctx) ; 
140165
141166    // Create static panner node 
142167    let  panner = ctx. create_panner ( ) ; 
@@ -159,8 +184,7 @@ pub fn bench_stereo_positional() {
159184
160185pub  fn  bench_stereo_panning_automation ( )  { 
161186    let  ctx = OfflineAudioContext :: new ( 2 ,  black_box ( SAMPLES ) ,  SAMPLE_RATE ) ; 
162-     let  file = std:: fs:: File :: open ( "samples/think-stereo-48000.wav" ) . unwrap ( ) ; 
163-     let  buffer = ctx. decode_audio_data_sync ( file) . unwrap ( ) ; 
187+     let  buffer = get_audio_buffer ( & ctx) ; 
164188
165189    let  panner = ctx. create_stereo_panner ( ) ; 
166190    panner. connect ( & ctx. destination ( ) ) ; 
@@ -181,8 +205,7 @@ pub fn bench_stereo_panning_automation() {
181205// benchmark this in deterministic way [citation needed]. 
182206pub  fn  bench_analyser_node ( )  { 
183207    let  ctx = OfflineAudioContext :: new ( 2 ,  black_box ( SAMPLES ) ,  SAMPLE_RATE ) ; 
184-     let  file = std:: fs:: File :: open ( "samples/think-stereo-48000.wav" ) . unwrap ( ) ; 
185-     let  buffer = ctx. decode_audio_data_sync ( file) . unwrap ( ) ; 
208+     let  buffer = get_audio_buffer ( & ctx) ; 
186209
187210    let  analyser = ctx. create_analyser ( ) ; 
188211    analyser. connect ( & ctx. destination ( ) ) ; 
@@ -197,7 +220,7 @@ pub fn bench_analyser_node() {
197220} 
198221
199222pub  fn  bench_hrtf_panners ( )  { 
200-     let  ctx = OfflineAudioContext :: new ( 2 ,  black_box ( SAMPLES ) ,  SAMPLE_RATE ) ; 
223+     let  ctx = OfflineAudioContext :: new ( 2 ,  black_box ( SAMPLES_SHORT ) ,  SAMPLE_RATE ) ; 
201224
202225    let  mut  panner1 = ctx. create_panner ( ) ; 
203226    panner1. set_panning_model ( PanningModelType :: HRTF ) ; 
@@ -214,11 +237,13 @@ pub fn bench_hrtf_panners() {
214237    osc. connect ( & panner2) ; 
215238    osc. start ( ) ; 
216239
217-     assert_eq ! ( ctx. start_rendering_sync( ) . length( ) ,  SAMPLES ) ; 
240+     assert_eq ! ( ctx. start_rendering_sync( ) . length( ) ,  SAMPLES_SHORT ) ; 
218241} 
219242
243+ #[ cfg( feature = "iai" ) ]  
220244iai:: main!( 
221245    bench_ctor, 
246+     bench_audio_buffer_decode, 
222247    bench_sine, 
223248    bench_sine_gain, 
224249    bench_sine_gain_delay, 
@@ -231,3 +256,85 @@ iai::main!(
231256    bench_analyser_node, 
232257    bench_hrtf_panners, 
233258) ; 
259+ 
260+ #[ cfg( not( feature = "iai" ) ) ]  
261+ fn  criterion_ctor ( c :  & mut  Criterion )  { 
262+     c. bench_function ( "bench_ctor" ,  |b| b. iter ( bench_ctor) ) ; 
263+ } 
264+ #[ cfg( not( feature = "iai" ) ) ]  
265+ fn  criterion_audio_buffer_decode ( c :  & mut  Criterion )  { 
266+     c. bench_function ( "bench_audio_buffer_decode" ,  |b| { 
267+         b. iter ( bench_audio_buffer_decode) 
268+     } ) ; 
269+ } 
270+ #[ cfg( not( feature = "iai" ) ) ]  
271+ fn  criterion_sine ( c :  & mut  Criterion )  { 
272+     c. bench_function ( "bench_sine" ,  |b| b. iter ( bench_sine) ) ; 
273+ } 
274+ #[ cfg( not( feature = "iai" ) ) ]  
275+ fn  criterion_sine_gain ( c :  & mut  Criterion )  { 
276+     c. bench_function ( "bench_sine_gain" ,  |b| b. iter ( bench_sine_gain) ) ; 
277+ } 
278+ #[ cfg( not( feature = "iai" ) ) ]  
279+ fn  criterion_sine_gain_delay ( c :  & mut  Criterion )  { 
280+     c. bench_function ( "bench_sine_gain_delay" ,  |b| b. iter ( bench_sine_gain_delay) ) ; 
281+ } 
282+ #[ cfg( not( feature = "iai" ) ) ]  
283+ fn  criterion_buffer_src ( c :  & mut  Criterion )  { 
284+     c. bench_function ( "bench_buffer_src" ,  |b| b. iter ( bench_buffer_src) ) ; 
285+ } 
286+ #[ cfg( not( feature = "iai" ) ) ]  
287+ fn  criterion_buffer_src_delay ( c :  & mut  Criterion )  { 
288+     c. bench_function ( "bench_buffer_src_delay" ,  |b| b. iter ( bench_buffer_src_delay) ) ; 
289+ } 
290+ #[ cfg( not( feature = "iai" ) ) ]  
291+ fn  criterion_buffer_src_iir ( c :  & mut  Criterion )  { 
292+     c. bench_function ( "bench_buffer_src_iir" ,  |b| b. iter ( bench_buffer_src_iir) ) ; 
293+ } 
294+ #[ cfg( not( feature = "iai" ) ) ]  
295+ fn  criterion_buffer_src_biquad ( c :  & mut  Criterion )  { 
296+     c. bench_function ( "bench_buffer_src_biquad" ,  |b| { 
297+         b. iter ( bench_buffer_src_biquad) 
298+     } ) ; 
299+ } 
300+ #[ cfg( not( feature = "iai" ) ) ]  
301+ fn  criterion_stereo_positional ( c :  & mut  Criterion )  { 
302+     c. bench_function ( "bench_stereo_positional" ,  |b| { 
303+         b. iter ( bench_stereo_positional) 
304+     } ) ; 
305+ } 
306+ #[ cfg( not( feature = "iai" ) ) ]  
307+ fn  criterion_stereo_panning_automation ( c :  & mut  Criterion )  { 
308+     c. bench_function ( "bench_stereo_panning_automation" ,  |b| { 
309+         b. iter ( bench_stereo_panning_automation) 
310+     } ) ; 
311+ } 
312+ #[ cfg( not( feature = "iai" ) ) ]  
313+ fn  criterion_analyser_node ( c :  & mut  Criterion )  { 
314+     c. bench_function ( "bench_analyser_node" ,  |b| b. iter ( bench_analyser_node) ) ; 
315+ } 
316+ #[ cfg( not( feature = "iai" ) ) ]  
317+ fn  criterion_hrtf_panners ( c :  & mut  Criterion )  { 
318+     c. bench_function ( "bench_hrtf_panners" ,  |b| b. iter ( bench_hrtf_panners) ) ; 
319+ } 
320+ 
321+ #[ cfg( not( feature = "iai" ) ) ]  
322+ criterion_group ! ( 
323+     benches, 
324+     criterion_ctor, 
325+     criterion_audio_buffer_decode, 
326+     criterion_sine, 
327+     criterion_sine_gain, 
328+     criterion_sine_gain_delay, 
329+     criterion_buffer_src, 
330+     criterion_buffer_src_delay, 
331+     criterion_buffer_src_iir, 
332+     criterion_buffer_src_biquad, 
333+     criterion_stereo_positional, 
334+     criterion_stereo_panning_automation, 
335+     criterion_analyser_node, 
336+     criterion_hrtf_panners
337+ ) ; 
338+ 
339+ #[ cfg( not( feature = "iai" ) ) ]  
340+ criterion_main ! ( benches) ; 
0 commit comments