@@ -655,7 +655,7 @@ impl AudioProcessor for AudioBufferSourceRenderer {
655
655
if !self . render_state . started {
656
656
let delta = current_time - self . start_time ;
657
657
// handle that start time may be between last sample and this one
658
- self . offset += delta;
658
+ self . offset += delta * computed_playback_rate ;
659
659
660
660
if is_looping && computed_playback_rate >= 0. && self . offset >= actual_loop_end
661
661
{
@@ -667,7 +667,7 @@ impl AudioProcessor for AudioBufferSourceRenderer {
667
667
self . offset = actual_loop_start;
668
668
}
669
669
670
- buffer_time = self . offset * computed_playback_rate ;
670
+ buffer_time = self . offset ;
671
671
self . render_state . buffer_time_elapsed = delta * computed_playback_rate;
672
672
self . render_state . started = true ;
673
673
}
@@ -1222,6 +1222,42 @@ mod tests {
1222
1222
assert_float_eq ! ( channel[ ..] , expected[ ..] , abs_all <= 1e-6 ) ;
1223
1223
}
1224
1224
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
+
1225
1261
#[ test]
1226
1262
fn test_detune ( ) {
1227
1263
let sample_rate = 44_100 ;
0 commit comments