Skip to content

Commit ce36241

Browse files
authored
Merge pull request #541 from b-ma/fix/absn-backward-playback
Fix ABSN backward playback
2 parents f5b1a7f + a6f123c commit ce36241

File tree

1 file changed

+38
-2
lines changed

1 file changed

+38
-2
lines changed

src/node/audio_buffer_source.rs

+38-2
Original file line numberDiff line numberDiff line change
@@ -655,7 +655,7 @@ impl AudioProcessor for AudioBufferSourceRenderer {
655655
if !self.render_state.started {
656656
let delta = current_time - self.start_time;
657657
// handle that start time may be between last sample and this one
658-
self.offset += delta;
658+
self.offset += delta * computed_playback_rate;
659659

660660
if is_looping && computed_playback_rate >= 0. && self.offset >= actual_loop_end
661661
{
@@ -667,7 +667,7 @@ impl AudioProcessor for AudioBufferSourceRenderer {
667667
self.offset = actual_loop_start;
668668
}
669669

670-
buffer_time = self.offset * computed_playback_rate;
670+
buffer_time = self.offset;
671671
self.render_state.buffer_time_elapsed = delta * computed_playback_rate;
672672
self.render_state.started = true;
673673
}
@@ -1222,6 +1222,42 @@ mod tests {
12221222
assert_float_eq!(channel[..], expected[..], abs_all <= 1e-6);
12231223
}
12241224

1225+
#[test]
1226+
fn test_negative_playback_rate() {
1227+
let sample_rate = 44_100;
1228+
let mut context = OfflineAudioContext::new(1, sample_rate, sample_rate as f32);
1229+
1230+
let mut buffer = context.create_buffer(1, sample_rate, sample_rate as f32);
1231+
let mut sine = vec![];
1232+
1233+
// 1 Hz sine
1234+
for i in 0..sample_rate {
1235+
let phase = i as f32 / sample_rate as f32 * 2. * PI;
1236+
let sample = phase.sin();
1237+
sine.push(sample);
1238+
}
1239+
1240+
buffer.copy_to_channel(&sine[..], 0);
1241+
1242+
let mut src = context.create_buffer_source();
1243+
src.connect(&context.destination());
1244+
src.set_buffer(buffer.clone());
1245+
src.playback_rate.set_value(-1.);
1246+
src.start_at_with_offset(context.current_time(), buffer.duration());
1247+
1248+
let result = context.start_rendering_sync();
1249+
let channel = result.get_channel_data(0);
1250+
1251+
// -1 Hz sine
1252+
let mut expected: Vec<f32> = sine.into_iter().rev().collect();
1253+
// offset is at duration (after last sample), then result will start
1254+
// with a zero value
1255+
expected.pop();
1256+
expected.insert(0, 0.);
1257+
1258+
assert_float_eq!(channel[..], expected[..], abs_all <= 1e-6);
1259+
}
1260+
12251261
#[test]
12261262
fn test_detune() {
12271263
let sample_rate = 44_100;

0 commit comments

Comments
 (0)