1
+ #[ cfg( feature = "iai" ) ]
1
2
use iai:: black_box;
2
3
4
+ #[ cfg( not( feature = "iai" ) ) ]
5
+ use criterion:: { black_box, criterion_group, criterion_main, Criterion } ;
6
+
3
7
use web_audio_api:: context:: BaseAudioContext ;
4
8
use web_audio_api:: context:: OfflineAudioContext ;
5
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 ;
6
14
7
15
const SAMPLE_RATE : f32 = 48000. ;
8
16
const DURATION : usize = 10 ;
9
17
const 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
+ }
10
34
11
35
pub fn bench_ctor ( ) {
12
36
let ctx = OfflineAudioContext :: new ( 2 , black_box ( SAMPLES ) , SAMPLE_RATE ) ;
13
37
assert_eq ! ( ctx. start_rendering_sync( ) . length( ) , SAMPLES ) ;
14
38
}
15
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
+
16
48
pub fn bench_sine ( ) {
17
49
let ctx = OfflineAudioContext :: new ( 2 , black_box ( SAMPLES ) , SAMPLE_RATE ) ;
18
50
let mut osc = ctx. create_oscillator ( ) ;
@@ -56,9 +88,7 @@ pub fn bench_sine_gain_delay() {
56
88
57
89
pub fn bench_buffer_src ( ) {
58
90
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) ;
62
92
63
93
let mut src = ctx. create_buffer_source ( ) ;
64
94
src. connect ( & ctx. destination ( ) ) ;
@@ -70,9 +100,7 @@ pub fn bench_buffer_src() {
70
100
71
101
pub fn bench_buffer_src_delay ( ) {
72
102
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) ;
76
104
77
105
let delay = ctx. create_delay ( 0.3 ) ;
78
106
delay. delay_time ( ) . set_value ( 0.2 ) ;
@@ -89,8 +117,7 @@ pub fn bench_buffer_src_delay() {
89
117
90
118
pub fn bench_buffer_src_iir ( ) {
91
119
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) ;
94
121
95
122
// these values correspond to a lowpass filter at 200Hz (calculated from biquad)
96
123
let feedforward = vec ! [
@@ -116,8 +143,7 @@ pub fn bench_buffer_src_iir() {
116
143
117
144
pub fn bench_buffer_src_biquad ( ) {
118
145
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) ;
121
147
122
148
// Create an biquad filter node (defaults to low pass)
123
149
let biquad = ctx. create_biquad_filter ( ) ;
@@ -135,8 +161,7 @@ pub fn bench_buffer_src_biquad() {
135
161
136
162
pub fn bench_stereo_positional ( ) {
137
163
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) ;
140
165
141
166
// Create static panner node
142
167
let panner = ctx. create_panner ( ) ;
@@ -159,8 +184,7 @@ pub fn bench_stereo_positional() {
159
184
160
185
pub fn bench_stereo_panning_automation ( ) {
161
186
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) ;
164
188
165
189
let panner = ctx. create_stereo_panner ( ) ;
166
190
panner. connect ( & ctx. destination ( ) ) ;
@@ -181,8 +205,7 @@ pub fn bench_stereo_panning_automation() {
181
205
// benchmark this in deterministic way [citation needed].
182
206
pub fn bench_analyser_node ( ) {
183
207
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) ;
186
209
187
210
let analyser = ctx. create_analyser ( ) ;
188
211
analyser. connect ( & ctx. destination ( ) ) ;
@@ -197,7 +220,7 @@ pub fn bench_analyser_node() {
197
220
}
198
221
199
222
pub 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 ) ;
201
224
202
225
let mut panner1 = ctx. create_panner ( ) ;
203
226
panner1. set_panning_model ( PanningModelType :: HRTF ) ;
@@ -214,11 +237,13 @@ pub fn bench_hrtf_panners() {
214
237
osc. connect ( & panner2) ;
215
238
osc. start ( ) ;
216
239
217
- assert_eq ! ( ctx. start_rendering_sync( ) . length( ) , SAMPLES ) ;
240
+ assert_eq ! ( ctx. start_rendering_sync( ) . length( ) , SAMPLES_SHORT ) ;
218
241
}
219
242
243
+ #[ cfg( feature = "iai" ) ]
220
244
iai:: main!(
221
245
bench_ctor,
246
+ bench_audio_buffer_decode,
222
247
bench_sine,
223
248
bench_sine_gain,
224
249
bench_sine_gain_delay,
@@ -231,3 +256,85 @@ iai::main!(
231
256
bench_analyser_node,
232
257
bench_hrtf_panners,
233
258
) ;
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