@@ -7,16 +7,44 @@ use criterion::{black_box, criterion_group, criterion_main, Criterion};
77use web_audio_api:: context:: BaseAudioContext ;
88use web_audio_api:: context:: OfflineAudioContext ;
99use web_audio_api:: node:: { AudioNode , AudioScheduledSourceNode , PanningModelType } ;
10+ use web_audio_api:: AudioBuffer ;
11+
12+ use std:: fs:: File ;
13+ use std:: sync:: OnceLock ;
1014
1115const SAMPLE_RATE : f32 = 48000. ;
1216const DURATION : usize = 10 ;
1317const SAMPLES : usize = SAMPLE_RATE as usize * DURATION ;
1418
19+ /// Load an audio buffer and cache the result
20+ ///
21+ /// We don't want to measure the IO and decoding in most of our benchmarks, so by using this static
22+ /// instance we avoid this in the criterion benchmarks because the file is already loaded in the
23+ /// warmup phase.
24+ fn get_audio_buffer ( ctx : & OfflineAudioContext ) -> AudioBuffer {
25+ static BUFFER : OnceLock < AudioBuffer > = OnceLock :: new ( ) ;
26+ BUFFER
27+ . get_or_init ( || {
28+ println ! ( "decoding now" ) ;
29+ let file = File :: open ( "samples/think-stereo-48000.wav" ) . unwrap ( ) ;
30+ ctx. decode_audio_data_sync ( file) . unwrap ( )
31+ } )
32+ . clone ( )
33+ }
34+
1535pub fn bench_ctor ( ) {
1636 let ctx = OfflineAudioContext :: new ( 2 , black_box ( SAMPLES ) , SAMPLE_RATE ) ;
1737 assert_eq ! ( ctx. start_rendering_sync( ) . length( ) , SAMPLES ) ;
1838}
1939
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+
2048pub fn bench_sine ( ) {
2149 let ctx = OfflineAudioContext :: new ( 2 , black_box ( SAMPLES ) , SAMPLE_RATE ) ;
2250 let mut osc = ctx. create_oscillator ( ) ;
@@ -60,9 +88,7 @@ pub fn bench_sine_gain_delay() {
6088
6189pub fn bench_buffer_src ( ) {
6290 let ctx = OfflineAudioContext :: new ( 2 , black_box ( SAMPLES ) , SAMPLE_RATE ) ;
63-
64- let file = std:: fs:: File :: open ( "samples/think-stereo-48000.wav" ) . unwrap ( ) ;
65- let buffer = ctx. decode_audio_data_sync ( file) . unwrap ( ) ;
91+ let buffer = get_audio_buffer ( & ctx) ;
6692
6793 let mut src = ctx. create_buffer_source ( ) ;
6894 src. connect ( & ctx. destination ( ) ) ;
@@ -74,9 +100,7 @@ pub fn bench_buffer_src() {
74100
75101pub fn bench_buffer_src_delay ( ) {
76102 let ctx = OfflineAudioContext :: new ( 2 , black_box ( SAMPLES ) , SAMPLE_RATE ) ;
77-
78- let file = std:: fs:: File :: open ( "samples/think-stereo-48000.wav" ) . unwrap ( ) ;
79- let buffer = ctx. decode_audio_data_sync ( file) . unwrap ( ) ;
103+ let buffer = get_audio_buffer ( & ctx) ;
80104
81105 let delay = ctx. create_delay ( 0.3 ) ;
82106 delay. delay_time ( ) . set_value ( 0.2 ) ;
@@ -93,8 +117,7 @@ pub fn bench_buffer_src_delay() {
93117
94118pub fn bench_buffer_src_iir ( ) {
95119 let ctx = OfflineAudioContext :: new ( 2 , black_box ( SAMPLES ) , SAMPLE_RATE ) ;
96- let file = std:: fs:: File :: open ( "samples/think-stereo-48000.wav" ) . unwrap ( ) ;
97- let buffer = ctx. decode_audio_data_sync ( file) . unwrap ( ) ;
120+ let buffer = get_audio_buffer ( & ctx) ;
98121
99122 // these values correspond to a lowpass filter at 200Hz (calculated from biquad)
100123 let feedforward = vec ! [
@@ -120,8 +143,7 @@ pub fn bench_buffer_src_iir() {
120143
121144pub fn bench_buffer_src_biquad ( ) {
122145 let ctx = OfflineAudioContext :: new ( 2 , black_box ( SAMPLES ) , SAMPLE_RATE ) ;
123- let file = std:: fs:: File :: open ( "samples/think-stereo-48000.wav" ) . unwrap ( ) ;
124- let buffer = ctx. decode_audio_data_sync ( file) . unwrap ( ) ;
146+ let buffer = get_audio_buffer ( & ctx) ;
125147
126148 // Create an biquad filter node (defaults to low pass)
127149 let biquad = ctx. create_biquad_filter ( ) ;
@@ -139,8 +161,7 @@ pub fn bench_buffer_src_biquad() {
139161
140162pub fn bench_stereo_positional ( ) {
141163 let ctx = OfflineAudioContext :: new ( 2 , black_box ( SAMPLES ) , SAMPLE_RATE ) ;
142- let file = std:: fs:: File :: open ( "samples/think-stereo-48000.wav" ) . unwrap ( ) ;
143- let buffer = ctx. decode_audio_data_sync ( file) . unwrap ( ) ;
164+ let buffer = get_audio_buffer ( & ctx) ;
144165
145166 // Create static panner node
146167 let panner = ctx. create_panner ( ) ;
@@ -163,8 +184,7 @@ pub fn bench_stereo_positional() {
163184
164185pub fn bench_stereo_panning_automation ( ) {
165186 let ctx = OfflineAudioContext :: new ( 2 , black_box ( SAMPLES ) , SAMPLE_RATE ) ;
166- let file = std:: fs:: File :: open ( "samples/think-stereo-48000.wav" ) . unwrap ( ) ;
167- let buffer = ctx. decode_audio_data_sync ( file) . unwrap ( ) ;
187+ let buffer = get_audio_buffer ( & ctx) ;
168188
169189 let panner = ctx. create_stereo_panner ( ) ;
170190 panner. connect ( & ctx. destination ( ) ) ;
@@ -185,8 +205,7 @@ pub fn bench_stereo_panning_automation() {
185205// benchmark this in deterministic way [citation needed].
186206pub fn bench_analyser_node ( ) {
187207 let ctx = OfflineAudioContext :: new ( 2 , black_box ( SAMPLES ) , SAMPLE_RATE ) ;
188- let file = std:: fs:: File :: open ( "samples/think-stereo-48000.wav" ) . unwrap ( ) ;
189- let buffer = ctx. decode_audio_data_sync ( file) . unwrap ( ) ;
208+ let buffer = get_audio_buffer ( & ctx) ;
190209
191210 let analyser = ctx. create_analyser ( ) ;
192211 analyser. connect ( & ctx. destination ( ) ) ;
@@ -224,6 +243,7 @@ pub fn bench_hrtf_panners() {
224243#[ cfg( feature = "iai" ) ]
225244iai:: main!(
226245 bench_ctor,
246+ bench_audio_buffer_decode,
227247 bench_sine,
228248 bench_sine_gain,
229249 bench_sine_gain_delay,
@@ -242,6 +262,12 @@ fn criterion_ctor(c: &mut Criterion) {
242262 c. bench_function ( "bench_ctor" , |b| b. iter ( || bench_ctor ( ) ) ) ;
243263}
244264#[ 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" ) ) ]
245271fn criterion_sine ( c : & mut Criterion ) {
246272 c. bench_function ( "bench_sine" , |b| b. iter ( || bench_sine ( ) ) ) ;
247273}
@@ -302,6 +328,7 @@ fn criterion_hrtf_panners(c: &mut Criterion) {
302328criterion_group ! (
303329 benches,
304330 criterion_ctor,
331+ criterion_audio_buffer_decode,
305332 criterion_sine,
306333 criterion_sine_gain,
307334 criterion_sine_gain_delay,
0 commit comments