@@ -7,16 +7,44 @@ use criterion::{black_box, criterion_group, criterion_main, Criterion};
7
7
use web_audio_api:: context:: BaseAudioContext ;
8
8
use web_audio_api:: context:: OfflineAudioContext ;
9
9
use web_audio_api:: node:: { AudioNode , AudioScheduledSourceNode , PanningModelType } ;
10
+ use web_audio_api:: AudioBuffer ;
11
+
12
+ use std:: fs:: File ;
13
+ use std:: sync:: OnceLock ;
10
14
11
15
const SAMPLE_RATE : f32 = 48000. ;
12
16
const DURATION : usize = 10 ;
13
17
const SAMPLES : usize = SAMPLE_RATE as usize * DURATION ;
14
18
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
+
15
35
pub fn bench_ctor ( ) {
16
36
let ctx = OfflineAudioContext :: new ( 2 , black_box ( SAMPLES ) , SAMPLE_RATE ) ;
17
37
assert_eq ! ( ctx. start_rendering_sync( ) . length( ) , SAMPLES ) ;
18
38
}
19
39
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
+
20
48
pub fn bench_sine ( ) {
21
49
let ctx = OfflineAudioContext :: new ( 2 , black_box ( SAMPLES ) , SAMPLE_RATE ) ;
22
50
let mut osc = ctx. create_oscillator ( ) ;
@@ -60,9 +88,7 @@ pub fn bench_sine_gain_delay() {
60
88
61
89
pub fn bench_buffer_src ( ) {
62
90
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) ;
66
92
67
93
let mut src = ctx. create_buffer_source ( ) ;
68
94
src. connect ( & ctx. destination ( ) ) ;
@@ -74,9 +100,7 @@ pub fn bench_buffer_src() {
74
100
75
101
pub fn bench_buffer_src_delay ( ) {
76
102
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) ;
80
104
81
105
let delay = ctx. create_delay ( 0.3 ) ;
82
106
delay. delay_time ( ) . set_value ( 0.2 ) ;
@@ -93,8 +117,7 @@ pub fn bench_buffer_src_delay() {
93
117
94
118
pub fn bench_buffer_src_iir ( ) {
95
119
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) ;
98
121
99
122
// these values correspond to a lowpass filter at 200Hz (calculated from biquad)
100
123
let feedforward = vec ! [
@@ -120,8 +143,7 @@ pub fn bench_buffer_src_iir() {
120
143
121
144
pub fn bench_buffer_src_biquad ( ) {
122
145
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) ;
125
147
126
148
// Create an biquad filter node (defaults to low pass)
127
149
let biquad = ctx. create_biquad_filter ( ) ;
@@ -139,8 +161,7 @@ pub fn bench_buffer_src_biquad() {
139
161
140
162
pub fn bench_stereo_positional ( ) {
141
163
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) ;
144
165
145
166
// Create static panner node
146
167
let panner = ctx. create_panner ( ) ;
@@ -163,8 +184,7 @@ pub fn bench_stereo_positional() {
163
184
164
185
pub fn bench_stereo_panning_automation ( ) {
165
186
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) ;
168
188
169
189
let panner = ctx. create_stereo_panner ( ) ;
170
190
panner. connect ( & ctx. destination ( ) ) ;
@@ -185,8 +205,7 @@ pub fn bench_stereo_panning_automation() {
185
205
// benchmark this in deterministic way [citation needed].
186
206
pub fn bench_analyser_node ( ) {
187
207
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) ;
190
209
191
210
let analyser = ctx. create_analyser ( ) ;
192
211
analyser. connect ( & ctx. destination ( ) ) ;
@@ -224,6 +243,7 @@ pub fn bench_hrtf_panners() {
224
243
#[ cfg( feature = "iai" ) ]
225
244
iai:: main!(
226
245
bench_ctor,
246
+ bench_audio_buffer_decode,
227
247
bench_sine,
228
248
bench_sine_gain,
229
249
bench_sine_gain_delay,
@@ -242,6 +262,12 @@ fn criterion_ctor(c: &mut Criterion) {
242
262
c. bench_function ( "bench_ctor" , |b| b. iter ( || bench_ctor ( ) ) ) ;
243
263
}
244
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" ) ) ]
245
271
fn criterion_sine ( c : & mut Criterion ) {
246
272
c. bench_function ( "bench_sine" , |b| b. iter ( || bench_sine ( ) ) ) ;
247
273
}
@@ -302,6 +328,7 @@ fn criterion_hrtf_panners(c: &mut Criterion) {
302
328
criterion_group ! (
303
329
benches,
304
330
criterion_ctor,
331
+ criterion_audio_buffer_decode,
305
332
criterion_sine,
306
333
criterion_sine_gain,
307
334
criterion_sine_gain_delay,
0 commit comments