Skip to content

Commit c9bc08f

Browse files
authored
Merge pull request #405 from orottier/feature/offline-audio-context-start-rendering
OfflineAudioContext::start_rendering_sync now takes &mut instead of self
2 parents 935de1b + b75cc37 commit c9bc08f

18 files changed

+118
-100
lines changed

benches/my_benchmark.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ fn get_audio_buffer(ctx: &OfflineAudioContext) -> AudioBuffer {
3838
}
3939

4040
pub fn bench_ctor() {
41-
let ctx = OfflineAudioContext::new(2, black_box(SAMPLES), SAMPLE_RATE);
41+
let mut ctx = OfflineAudioContext::new(2, black_box(SAMPLES), SAMPLE_RATE);
4242
assert_eq!(ctx.start_rendering_sync().length(), SAMPLES);
4343
}
4444

@@ -51,7 +51,7 @@ pub fn bench_audio_buffer_decode() {
5151
}
5252

5353
pub fn bench_sine() {
54-
let ctx = OfflineAudioContext::new(2, black_box(SAMPLES), SAMPLE_RATE);
54+
let mut ctx = OfflineAudioContext::new(2, black_box(SAMPLES), SAMPLE_RATE);
5555
let mut osc = ctx.create_oscillator();
5656

5757
osc.connect(&ctx.destination());
@@ -61,7 +61,7 @@ pub fn bench_sine() {
6161
}
6262

6363
pub fn bench_sine_gain() {
64-
let ctx = OfflineAudioContext::new(2, black_box(SAMPLES), SAMPLE_RATE);
64+
let mut ctx = OfflineAudioContext::new(2, black_box(SAMPLES), SAMPLE_RATE);
6565
let mut osc = ctx.create_oscillator();
6666
let gain = ctx.create_gain();
6767
gain.gain().set_value(0.5); // avoid happy path
@@ -75,7 +75,7 @@ pub fn bench_sine_gain() {
7575
}
7676

7777
pub fn bench_sine_gain_delay() {
78-
let ctx = OfflineAudioContext::new(2, black_box(SAMPLES), SAMPLE_RATE);
78+
let mut ctx = OfflineAudioContext::new(2, black_box(SAMPLES), SAMPLE_RATE);
7979

8080
let mut osc = ctx.create_oscillator();
8181
let gain = ctx.create_gain();
@@ -93,7 +93,7 @@ pub fn bench_sine_gain_delay() {
9393
}
9494

9595
pub fn bench_buffer_src() {
96-
let ctx = OfflineAudioContext::new(2, black_box(SAMPLES), SAMPLE_RATE);
96+
let mut ctx = OfflineAudioContext::new(2, black_box(SAMPLES), SAMPLE_RATE);
9797
let buffer = get_audio_buffer(&ctx);
9898

9999
let mut src = ctx.create_buffer_source();
@@ -105,7 +105,7 @@ pub fn bench_buffer_src() {
105105
}
106106

107107
pub fn bench_buffer_src_delay() {
108-
let ctx = OfflineAudioContext::new(2, black_box(SAMPLES), SAMPLE_RATE);
108+
let mut ctx = OfflineAudioContext::new(2, black_box(SAMPLES), SAMPLE_RATE);
109109
let buffer = get_audio_buffer(&ctx);
110110

111111
let delay = ctx.create_delay(0.3);
@@ -122,7 +122,7 @@ pub fn bench_buffer_src_delay() {
122122
}
123123

124124
pub fn bench_buffer_src_iir() {
125-
let ctx = OfflineAudioContext::new(2, black_box(SAMPLES), SAMPLE_RATE);
125+
let mut ctx = OfflineAudioContext::new(2, black_box(SAMPLES), SAMPLE_RATE);
126126
let buffer = get_audio_buffer(&ctx);
127127

128128
// these values correspond to a lowpass filter at 200Hz (calculated from biquad)
@@ -148,7 +148,7 @@ pub fn bench_buffer_src_iir() {
148148
}
149149

150150
pub fn bench_buffer_src_biquad() {
151-
let ctx = OfflineAudioContext::new(2, black_box(SAMPLES), SAMPLE_RATE);
151+
let mut ctx = OfflineAudioContext::new(2, black_box(SAMPLES), SAMPLE_RATE);
152152
let buffer = get_audio_buffer(&ctx);
153153

154154
// Create an biquad filter node (defaults to low pass)
@@ -166,7 +166,7 @@ pub fn bench_buffer_src_biquad() {
166166
}
167167

168168
pub fn bench_stereo_positional() {
169-
let ctx = OfflineAudioContext::new(2, black_box(SAMPLES), SAMPLE_RATE);
169+
let mut ctx = OfflineAudioContext::new(2, black_box(SAMPLES), SAMPLE_RATE);
170170
let buffer = get_audio_buffer(&ctx);
171171

172172
// Create static panner node
@@ -189,7 +189,7 @@ pub fn bench_stereo_positional() {
189189
}
190190

191191
pub fn bench_stereo_panning_automation() {
192-
let ctx = OfflineAudioContext::new(2, black_box(SAMPLES), SAMPLE_RATE);
192+
let mut ctx = OfflineAudioContext::new(2, black_box(SAMPLES), SAMPLE_RATE);
193193
let buffer = get_audio_buffer(&ctx);
194194

195195
let panner = ctx.create_stereo_panner();
@@ -210,7 +210,7 @@ pub fn bench_stereo_panning_automation() {
210210
// We don't request freq/time data because that happens off thread and there is no sensible way to
211211
// benchmark this in deterministic way [citation needed].
212212
pub fn bench_analyser_node() {
213-
let ctx = OfflineAudioContext::new(2, black_box(SAMPLES), SAMPLE_RATE);
213+
let mut ctx = OfflineAudioContext::new(2, black_box(SAMPLES), SAMPLE_RATE);
214214
let buffer = get_audio_buffer(&ctx);
215215

216216
let analyser = ctx.create_analyser();
@@ -226,7 +226,7 @@ pub fn bench_analyser_node() {
226226
}
227227

228228
pub fn bench_hrtf_panners() {
229-
let ctx = OfflineAudioContext::new(2, black_box(SAMPLES_SHORT), SAMPLE_RATE);
229+
let mut ctx = OfflineAudioContext::new(2, black_box(SAMPLES_SHORT), SAMPLE_RATE);
230230

231231
let mut panner1 = ctx.create_panner();
232232
panner1.set_panning_model(PanningModelType::HRTF);
@@ -247,7 +247,7 @@ pub fn bench_hrtf_panners() {
247247
}
248248

249249
pub fn bench_sine_gain_with_worklet() {
250-
let ctx = OfflineAudioContext::new(2, black_box(SAMPLES), SAMPLE_RATE);
250+
let mut ctx = OfflineAudioContext::new(2, black_box(SAMPLES), SAMPLE_RATE);
251251
let mut osc = ctx.create_oscillator();
252252

253253
let options = AudioWorkletNodeOptions::default();

examples/benchmarks.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ fn get_buffer(sources: &[AudioBuffer], sample_rate: f32, number_of_channels: usi
4545
buffer.unwrap().clone()
4646
}
4747

48-
fn benchmark(name: &'static str, context: OfflineAudioContext, results: &mut Vec<BenchResult>) {
48+
fn benchmark(name: &'static str, mut context: OfflineAudioContext, results: &mut Vec<BenchResult>) {
4949
print!("> Running benchmark: {:<70}\r", name);
5050
stdout().flush().unwrap();
5151

src/context/offline.rs

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pub struct OfflineAudioContext {
1717
/// the size of the buffer in sample-frames
1818
length: usize,
1919
/// the rendering 'thread', fully controlled by the offline context
20-
renderer: RenderThread,
20+
renderer: Option<RenderThread>,
2121
}
2222

2323
impl BaseAudioContext for OfflineAudioContext {
@@ -74,16 +74,24 @@ impl OfflineAudioContext {
7474
Self {
7575
base,
7676
length,
77-
renderer,
77+
renderer: Some(renderer),
7878
}
7979
}
8080

8181
/// Given the current connections and scheduled changes, starts rendering audio.
8282
///
8383
/// This function will block the current thread and returns the rendered `AudioBuffer`
8484
/// synchronously. An async version is currently not implemented.
85-
pub fn start_rendering_sync(self) -> AudioBuffer {
86-
self.renderer.render_audiobuffer_sync(self.length)
85+
///
86+
/// # Panics
87+
///
88+
/// Panics if this method is called multiple times
89+
pub fn start_rendering_sync(&mut self) -> AudioBuffer {
90+
let renderer = match self.renderer.take() {
91+
None => panic!("InvalidStateError: Cannot call `startRendering` twice"),
92+
Some(v) => v,
93+
};
94+
renderer.render_audiobuffer_sync(self.length)
8795
}
8896

8997
/// get the length of rendering audio buffer
@@ -102,12 +110,22 @@ mod tests {
102110

103111
#[test]
104112
fn render_empty_graph() {
105-
let context = OfflineAudioContext::new(2, 555, 44_100.);
113+
let mut context = OfflineAudioContext::new(2, 555, 44_100.);
106114
let buffer = context.start_rendering_sync();
107115

116+
assert_eq!(context.length(), 555);
117+
108118
assert_eq!(buffer.number_of_channels(), 2);
109119
assert_eq!(buffer.length(), 555);
110120
assert_float_eq!(buffer.get_channel_data(0), &[0.; 555][..], abs_all <= 0.);
111121
assert_float_eq!(buffer.get_channel_data(1), &[0.; 555][..], abs_all <= 0.);
112122
}
123+
124+
#[test]
125+
#[should_panic]
126+
fn render_twice_panics() {
127+
let mut context = OfflineAudioContext::new(2, 555, 44_100.);
128+
let _ = context.start_rendering_sync();
129+
let _ = context.start_rendering_sync();
130+
}
113131
}

src/node/audio_buffer_source.rs

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -796,7 +796,7 @@ mod tests {
796796
fn test_construct_with_options_and_run() {
797797
let sample_rate = 44100.;
798798
let length = RENDER_QUANTUM_SIZE;
799-
let context = OfflineAudioContext::new(1, length, sample_rate);
799+
let mut context = OfflineAudioContext::new(1, length, sample_rate);
800800

801801
let buffer = AudioBuffer::from(vec![vec![1.; RENDER_QUANTUM_SIZE]], sample_rate);
802802
let options = AudioBufferSourceOptions {
@@ -836,7 +836,7 @@ mod tests {
836836

837837
assert_eq!(audio_buffer.sample_rate(), *sr as f32);
838838

839-
let context = OfflineAudioContext::new(2, RENDER_QUANTUM_SIZE, 44_100.);
839+
let mut context = OfflineAudioContext::new(2, RENDER_QUANTUM_SIZE, 44_100.);
840840

841841
let mut src = context.create_buffer_source();
842842
src.set_buffer(audio_buffer);
@@ -873,7 +873,7 @@ mod tests {
873873
#[test]
874874
fn test_sub_quantum_start() {
875875
let sample_rate = 480000.;
876-
let context = OfflineAudioContext::new(1, RENDER_QUANTUM_SIZE, sample_rate);
876+
let mut context = OfflineAudioContext::new(1, RENDER_QUANTUM_SIZE, sample_rate);
877877

878878
let mut dirac = context.create_buffer(1, 1, sample_rate);
879879
dirac.copy_to_channel(&[1.], 0);
@@ -896,7 +896,7 @@ mod tests {
896896
fn test_sub_sample_start() {
897897
// sub sample
898898
let sample_rate = 480000.;
899-
let context = OfflineAudioContext::new(1, RENDER_QUANTUM_SIZE, sample_rate);
899+
let mut context = OfflineAudioContext::new(1, RENDER_QUANTUM_SIZE, sample_rate);
900900

901901
let mut dirac = context.create_buffer(1, 1, sample_rate);
902902
dirac.copy_to_channel(&[1.], 0);
@@ -920,7 +920,7 @@ mod tests {
920920
// fast track
921921
{
922922
let sample_rate = 480000.;
923-
let context = OfflineAudioContext::new(1, RENDER_QUANTUM_SIZE, sample_rate);
923+
let mut context = OfflineAudioContext::new(1, RENDER_QUANTUM_SIZE, sample_rate);
924924

925925
let mut dirac = context.create_buffer(1, RENDER_QUANTUM_SIZE, sample_rate);
926926
dirac.copy_to_channel(&[0., 0., 0., 0., 1.], 0);
@@ -942,7 +942,7 @@ mod tests {
942942
// slow track
943943
{
944944
let sample_rate = 480000.;
945-
let context = OfflineAudioContext::new(1, RENDER_QUANTUM_SIZE, sample_rate);
945+
let mut context = OfflineAudioContext::new(1, RENDER_QUANTUM_SIZE, sample_rate);
946946

947947
let mut dirac = context.create_buffer(1, RENDER_QUANTUM_SIZE, sample_rate);
948948
dirac.copy_to_channel(&[0., 0., 0., 0., 1.], 0);
@@ -967,7 +967,7 @@ mod tests {
967967
// fast track
968968
{
969969
let sample_rate = 480000.;
970-
let context = OfflineAudioContext::new(1, RENDER_QUANTUM_SIZE, sample_rate);
970+
let mut context = OfflineAudioContext::new(1, RENDER_QUANTUM_SIZE, sample_rate);
971971

972972
let mut dirac = context.create_buffer(1, RENDER_QUANTUM_SIZE, sample_rate);
973973
dirac.copy_to_channel(&[0., 0., 0., 0., 1., 1.], 0);
@@ -991,7 +991,7 @@ mod tests {
991991
// slow track
992992
{
993993
let sample_rate = 480000.;
994-
let context = OfflineAudioContext::new(1, RENDER_QUANTUM_SIZE, sample_rate);
994+
let mut context = OfflineAudioContext::new(1, RENDER_QUANTUM_SIZE, sample_rate);
995995

996996
let mut dirac = context.create_buffer(1, RENDER_QUANTUM_SIZE, sample_rate);
997997
dirac.copy_to_channel(&[0., 0., 0., 0., 1., 1.], 0);
@@ -1016,7 +1016,7 @@ mod tests {
10161016
#[test]
10171017
fn test_schedule_in_the_past() {
10181018
let sample_rate = 48000.;
1019-
let context = OfflineAudioContext::new(1, RENDER_QUANTUM_SIZE, sample_rate);
1019+
let mut context = OfflineAudioContext::new(1, RENDER_QUANTUM_SIZE, sample_rate);
10201020

10211021
let mut dirac = context.create_buffer(1, 1, sample_rate);
10221022
dirac.copy_to_channel(&[1.], 0);
@@ -1039,7 +1039,7 @@ mod tests {
10391039
fn test_audio_buffer_resampling() {
10401040
[22500, 38000, 48000, 96000].iter().for_each(|sr| {
10411041
let base_sr = 44100;
1042-
let context = OfflineAudioContext::new(1, base_sr, base_sr as f32);
1042+
let mut context = OfflineAudioContext::new(1, base_sr, base_sr as f32);
10431043

10441044
// 1Hz sine at different sample rates
10451045
let buf_sr = *sr;
@@ -1080,7 +1080,7 @@ mod tests {
10801080
#[test]
10811081
fn test_playback_rate() {
10821082
let sample_rate = 44100;
1083-
let context = OfflineAudioContext::new(1, sample_rate, sample_rate as f32);
1083+
let mut context = OfflineAudioContext::new(1, sample_rate, sample_rate as f32);
10841084

10851085
let mut buffer = context.create_buffer(1, sample_rate, sample_rate as f32);
10861086
let mut sine = vec![];
@@ -1118,7 +1118,7 @@ mod tests {
11181118
#[test]
11191119
fn test_detune() {
11201120
let sample_rate = 44100;
1121-
let context = OfflineAudioContext::new(1, sample_rate, sample_rate as f32);
1121+
let mut context = OfflineAudioContext::new(1, sample_rate, sample_rate as f32);
11221122

11231123
let mut buffer = context.create_buffer(1, sample_rate, sample_rate as f32);
11241124
let mut sine = vec![];
@@ -1158,7 +1158,7 @@ mod tests {
11581158
// fast track
11591159
{
11601160
let sample_rate = 480000.;
1161-
let context = OfflineAudioContext::new(1, RENDER_QUANTUM_SIZE * 2, sample_rate);
1161+
let mut context = OfflineAudioContext::new(1, RENDER_QUANTUM_SIZE * 2, sample_rate);
11621162

11631163
let mut buffer = context.create_buffer(1, 129, sample_rate);
11641164
let mut data = vec![0.; 129];
@@ -1184,7 +1184,7 @@ mod tests {
11841184
// slow track
11851185
{
11861186
let sample_rate = 480000.;
1187-
let context = OfflineAudioContext::new(1, RENDER_QUANTUM_SIZE * 2, sample_rate);
1187+
let mut context = OfflineAudioContext::new(1, RENDER_QUANTUM_SIZE * 2, sample_rate);
11881188

11891189
let mut buffer = context.create_buffer(1, 129, sample_rate);
11901190
let mut data = vec![0.; 129];
@@ -1213,7 +1213,7 @@ mod tests {
12131213
// fast track
12141214
{
12151215
let sample_rate = 480000.;
1216-
let context = OfflineAudioContext::new(1, RENDER_QUANTUM_SIZE, sample_rate);
1216+
let mut context = OfflineAudioContext::new(1, RENDER_QUANTUM_SIZE, sample_rate);
12171217

12181218
let mut dirac = context.create_buffer(1, RENDER_QUANTUM_SIZE, sample_rate);
12191219
dirac.copy_to_channel(&[0., 0., 0., 0., 1., 1.], 0);
@@ -1235,7 +1235,7 @@ mod tests {
12351235

12361236
{
12371237
let sample_rate = 480000.;
1238-
let context = OfflineAudioContext::new(1, RENDER_QUANTUM_SIZE, sample_rate);
1238+
let mut context = OfflineAudioContext::new(1, RENDER_QUANTUM_SIZE, sample_rate);
12391239

12401240
let mut dirac = context.create_buffer(1, RENDER_QUANTUM_SIZE, sample_rate);
12411241
dirac.copy_to_channel(&[0., 0., 0., 0., 1., 1.], 0);
@@ -1266,7 +1266,7 @@ mod tests {
12661266
fn test_with_offset() {
12671267
// offset always bypass slow track
12681268
let sample_rate = 480000.;
1269-
let context = OfflineAudioContext::new(1, RENDER_QUANTUM_SIZE, sample_rate);
1269+
let mut context = OfflineAudioContext::new(1, RENDER_QUANTUM_SIZE, sample_rate);
12701270

12711271
let mut dirac = context.create_buffer(1, RENDER_QUANTUM_SIZE, sample_rate);
12721272
dirac.copy_to_channel(&[0., 0., 0., 0., 1., 1.], 0);
@@ -1308,7 +1308,7 @@ mod tests {
13081308
RENDER_QUANTUM_SIZE * 2,
13091309
RENDER_QUANTUM_SIZE * 2 + 1,
13101310
] {
1311-
let context = OfflineAudioContext::new(1, len, sample_rate);
1311+
let mut context = OfflineAudioContext::new(1, len, sample_rate);
13121312

13131313
let mut dirac = context.create_buffer(1, buffer_len, sample_rate);
13141314
dirac.copy_to_channel(&[1.], 0);
@@ -1347,7 +1347,7 @@ mod tests {
13471347
RENDER_QUANTUM_SIZE * 2,
13481348
RENDER_QUANTUM_SIZE * 2 + 1,
13491349
] {
1350-
let context = OfflineAudioContext::new(2, len, sample_rate);
1350+
let mut context = OfflineAudioContext::new(2, len, sample_rate);
13511351
let mut dirac = context.create_buffer(2, buffer_len, sample_rate);
13521352
dirac.copy_to_channel(&[1.], 0);
13531353
dirac.copy_to_channel(&[0., 1.], 1);

src/node/constant_source.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ mod tests {
238238
let sample_rate = 48000.;
239239
let start_in_samples = (128 + 1) as f64; // start rendering in 2d block
240240
let stop_in_samples = (256 + 1) as f64; // stop rendering of 3rd block
241-
let context = OfflineAudioContext::new(1, 128 * 4, sample_rate);
241+
let mut context = OfflineAudioContext::new(1, 128 * 4, sample_rate);
242242

243243
let mut src = context.create_constant_source();
244244
src.connect(&context.destination());
@@ -268,7 +268,7 @@ mod tests {
268268

269269
#[test]
270270
fn test_start_in_the_past() {
271-
let context = OfflineAudioContext::new(1, 128, 48000.);
271+
let mut context = OfflineAudioContext::new(1, 128, 48000.);
272272

273273
let mut src = context.create_constant_source();
274274
src.connect(&context.destination());

src/node/convolver.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,7 @@ mod tests {
464464
#[test]
465465
fn test_constructor_options_buffer() {
466466
let sample_rate = 44100.;
467-
let context = OfflineAudioContext::new(1, 10, sample_rate);
467+
let mut context = OfflineAudioContext::new(1, 10, sample_rate);
468468

469469
let ir = vec![1.];
470470
let calibration = 0.00125;
@@ -493,7 +493,7 @@ mod tests {
493493

494494
fn test_convolve(signal: &[f32], impulse_resp: Option<Vec<f32>>, length: usize) -> AudioBuffer {
495495
let sample_rate = 44100.;
496-
let context = OfflineAudioContext::new(1, length, sample_rate);
496+
let mut context = OfflineAudioContext::new(1, length, sample_rate);
497497

498498
let input = AudioBuffer::from(vec![signal.to_vec()], sample_rate);
499499
let mut src = AudioBufferSourceNode::new(&context, AudioBufferSourceOptions::default());

0 commit comments

Comments
 (0)