@@ -197,24 +197,20 @@ impl DelayNode {
197
197
"NotSupportedError - maxDelayTime MUST be greater than zero and less than three minutes" ,
198
198
) ;
199
199
200
- // we internally clamp max delay to quantum duration because the current
201
- // implementation doesn't allow sub-quantum delays. Later, this will
202
- // ensure that even if the declared max_delay_time and max_delay are smaller
200
+ // wW internally clamp max delay to quantum duration. This ensure
201
+ // that even if the declared max_delay_time and max_delay are smaller
203
202
// than quantum duration, the node, if found in a loop, will gracefully
204
- // fallback to the clamped behavior. (e.g. we ensure that ring buffer size
205
- // is always >= 2)
203
+ // fallback to the clamped behavior. (e.g. we ensure that ring buffer
204
+ // size is always >= 2)
206
205
let quantum_duration = 1. / sample_rate * RENDER_QUANTUM_SIZE as f64 ;
207
206
let max_delay_time = options. max_delay_time . max ( quantum_duration) ;
208
207
209
- // allocate large enough buffer to store all delayed samples
210
- //
211
- // we add 1 here so that in edge cases where num_samples is a multiple of
212
- // RENDER_QUANTUM_SIZE and delay_time == max_delay_time we are sure to
213
- // enough room for history. (see. test_max_delay_multiple_of_quantum_size)
214
- let num_samples = max_delay_time * sample_rate + 1. ;
215
- let num_quanta =
216
- ( num_samples. ceil ( ) as usize + RENDER_QUANTUM_SIZE - 1 ) / RENDER_QUANTUM_SIZE ;
217
- let ring_buffer = Vec :: with_capacity ( num_quanta) ;
208
+ // Allocate large enough buffer to store all delayed samples.
209
+ // We add one extra buffer in the ring buffer so that reader never read the
210
+ // same entry in history as the writer, even if `delay_time === max_delay_time`
211
+ // cf. test_max_delay_multiple_of_quantum_size and test_max_delay
212
+ let num_quanta = ( max_delay_time * sample_rate / RENDER_QUANTUM_SIZE as f64 ) . ceil ( ) as usize ;
213
+ let ring_buffer = Vec :: with_capacity ( num_quanta + 1 ) ;
218
214
219
215
let shared_ring_buffer = Rc :: new ( RefCell :: new ( ring_buffer) ) ;
220
216
let shared_ring_buffer_clone = Rc :: clone ( & shared_ring_buffer) ;
@@ -707,60 +703,59 @@ mod tests {
707
703
}
708
704
709
705
#[ test]
710
- fn test_sub_sample_accurate ( ) {
711
- {
712
- let delay_in_samples = 128.5 ;
713
- let sample_rate = 48000. ;
714
- let mut context = OfflineAudioContext :: new ( 1 , 256 , sample_rate) ;
706
+ fn test_sub_sample_accurate_1 ( ) {
707
+ let delay_in_samples = 128.5 ;
708
+ let sample_rate = 48000. ;
709
+ let mut context = OfflineAudioContext :: new ( 1 , 256 , sample_rate) ;
715
710
716
- let delay = context. create_delay ( 2. ) ;
717
- delay. delay_time . set_value ( delay_in_samples / sample_rate) ;
718
- delay. connect ( & context. destination ( ) ) ;
711
+ let delay = context. create_delay ( 2. ) ;
712
+ delay. delay_time . set_value ( delay_in_samples / sample_rate) ;
713
+ delay. connect ( & context. destination ( ) ) ;
719
714
720
- let mut dirac = context. create_buffer ( 1 , 1 , sample_rate) ;
721
- dirac. copy_to_channel ( & [ 1. ] , 0 ) ;
715
+ let mut dirac = context. create_buffer ( 1 , 1 , sample_rate) ;
716
+ dirac. copy_to_channel ( & [ 1. ] , 0 ) ;
722
717
723
- let mut src = context. create_buffer_source ( ) ;
724
- src. connect ( & delay) ;
725
- src. set_buffer ( dirac) ;
726
- src. start_at ( 0. ) ;
718
+ let mut src = context. create_buffer_source ( ) ;
719
+ src. connect ( & delay) ;
720
+ src. set_buffer ( dirac) ;
721
+ src. start_at ( 0. ) ;
727
722
728
- let result = context. start_rendering_sync ( ) ;
729
- let channel = result. get_channel_data ( 0 ) ;
723
+ let result = context. start_rendering_sync ( ) ;
724
+ let channel = result. get_channel_data ( 0 ) ;
730
725
731
- let mut expected = vec ! [ 0. ; 256 ] ;
732
- expected[ 128 ] = 0.5 ;
733
- expected[ 129 ] = 0.5 ;
726
+ let mut expected = vec ! [ 0. ; 256 ] ;
727
+ expected[ 128 ] = 0.5 ;
728
+ expected[ 129 ] = 0.5 ;
734
729
735
- assert_float_eq ! ( channel[ ..] , expected[ ..] , abs_all <= 0.00001 ) ;
736
- }
730
+ assert_float_eq ! ( channel[ ..] , expected[ ..] , abs_all <= 0.00001 ) ;
731
+ }
737
732
738
- {
739
- let delay_in_samples = 128.8 ;
740
- let sample_rate = 48000. ;
741
- let mut context = OfflineAudioContext :: new ( 1 , 256 , sample_rate) ;
733
+ #[ test]
734
+ fn test_sub_sample_accurate_2 ( ) {
735
+ let delay_in_samples = 128.8 ;
736
+ let sample_rate = 48000. ;
737
+ let mut context = OfflineAudioContext :: new ( 1 , 256 , sample_rate) ;
742
738
743
- let delay = context. create_delay ( 2. ) ;
744
- delay. delay_time . set_value ( delay_in_samples / sample_rate) ;
745
- delay. connect ( & context. destination ( ) ) ;
739
+ let delay = context. create_delay ( 2. ) ;
740
+ delay. delay_time . set_value ( delay_in_samples / sample_rate) ;
741
+ delay. connect ( & context. destination ( ) ) ;
746
742
747
- let mut dirac = context. create_buffer ( 1 , 1 , sample_rate) ;
748
- dirac. copy_to_channel ( & [ 1. ] , 0 ) ;
743
+ let mut dirac = context. create_buffer ( 1 , 1 , sample_rate) ;
744
+ dirac. copy_to_channel ( & [ 1. ] , 0 ) ;
749
745
750
- let mut src = context. create_buffer_source ( ) ;
751
- src. connect ( & delay) ;
752
- src. set_buffer ( dirac) ;
753
- src. start_at ( 0. ) ;
746
+ let mut src = context. create_buffer_source ( ) ;
747
+ src. connect ( & delay) ;
748
+ src. set_buffer ( dirac) ;
749
+ src. start_at ( 0. ) ;
754
750
755
- let result = context. start_rendering_sync ( ) ;
756
- let channel = result. get_channel_data ( 0 ) ;
751
+ let result = context. start_rendering_sync ( ) ;
752
+ let channel = result. get_channel_data ( 0 ) ;
757
753
758
- let mut expected = vec ! [ 0. ; 256 ] ;
759
- expected[ 128 ] = 0.2 ;
760
- expected[ 129 ] = 0.8 ;
754
+ let mut expected = vec ! [ 0. ; 256 ] ;
755
+ expected[ 128 ] = 0.2 ;
756
+ expected[ 129 ] = 0.8 ;
761
757
762
- assert_float_eq ! ( channel[ ..] , expected[ ..] , abs_all <= 1e-5 ) ;
763
- }
758
+ assert_float_eq ! ( channel[ ..] , expected[ ..] , abs_all <= 1e-5 ) ;
764
759
}
765
760
766
761
#[ test]
@@ -935,6 +930,60 @@ mod tests {
935
930
assert_float_eq ! ( channel[ ..] , expected[ ..] , abs_all <= 0. ) ;
936
931
}
937
932
933
+ // reproduce wpt tests from
934
+ // - the-delaynode-interface/delaynode-max-default-delay.html
935
+ // - the-delaynode-interface/delaynode-max-nondefault-delay.html
936
+ #[ test]
937
+ fn test_max_delay ( ) {
938
+ use std:: f32:: consts:: PI ;
939
+
940
+ for & delay_time_seconds in [ 1. , 1.5 ] . iter ( ) {
941
+ let sample_rate = 44100.0 ;
942
+ let render_length = 4 * sample_rate as usize ;
943
+
944
+ let mut context = OfflineAudioContext :: new ( 1 , render_length, sample_rate) ;
945
+
946
+ // create 2 seconds tone buffer at 20Hz
947
+ let tone_frequency = 20. ;
948
+ let tone_length_seconds = 2. ;
949
+ let tone_length = tone_length_seconds as usize * sample_rate as usize ;
950
+ let mut tone_buffer = context. create_buffer ( 1 , tone_length, sample_rate) ;
951
+ let tone_data = tone_buffer. get_channel_data_mut ( 0 ) ;
952
+
953
+ for i in 0 ..tone_data. len ( ) {
954
+ tone_data[ i] = ( tone_frequency * 2.0 * PI * i as f32 / sample_rate) . sin ( ) ;
955
+ }
956
+
957
+ let mut buffer_source = context. create_buffer_source ( ) ;
958
+ buffer_source. set_buffer ( tone_buffer. clone ( ) ) ;
959
+
960
+ let delay = context. create_delay ( delay_time_seconds) ; // max delay defaults to 1 second
961
+ delay. delay_time . set_value ( delay_time_seconds as f32 ) ;
962
+
963
+ buffer_source. connect ( & delay) ;
964
+ delay. connect ( & context. destination ( ) ) ;
965
+ buffer_source. start_at ( 0. ) ;
966
+
967
+ let output = context. start_rendering_sync ( ) ;
968
+ let source = tone_buffer. get_channel_data ( 0 ) ;
969
+ let rendered = output. get_channel_data ( 0 ) ;
970
+
971
+ let delay_time_frames = ( delay_time_seconds * sample_rate as f64 ) as usize ;
972
+ let tone_length_frames = ( tone_length_seconds * sample_rate as f64 ) as usize ;
973
+
974
+ for i in 0 ..rendered. len ( ) {
975
+ if i < delay_time_frames {
976
+ assert_eq ! ( rendered[ i] , 0. ) ;
977
+ } else if i >= delay_time_frames && i < delay_time_frames + tone_length_frames {
978
+ let j = i - delay_time_frames;
979
+ assert_eq ! ( rendered[ i] , source[ j] ) ;
980
+ } else {
981
+ assert_eq ! ( rendered[ i] , 0. ) ;
982
+ }
983
+ }
984
+ }
985
+ }
986
+
938
987
#[ test]
939
988
fn test_max_delay_smaller_than_quantum_size ( ) {
940
989
// regression test that even if the declared max_delay_time is smaller than
@@ -975,66 +1024,65 @@ mod tests {
975
1024
}
976
1025
}
977
1026
1027
+ // test_max_delay_multiple_of_quantum_size_x
1028
+ // are regression test that delay node has always enough internal buffer size
1029
+ // when max_delay is a multiple of quantum size and delay == max_delay.
1030
+ // This bug only occurs when the Writer is called before than the Reader,
1031
+ // which is the case when not in a loop
978
1032
#[ test]
979
- fn test_max_delay_multiple_of_quantum_size ( ) {
980
- // regression test that delay node has always enough internal buffer size
981
- // when max_delay is a multiple of quantum size and delay == max_delay.
982
- // This bug only occurs when the Writer is called before than the Reader,
983
- // which is the case when not in a loop
984
-
1033
+ fn test_max_delay_multiple_of_quantum_size_1 ( ) {
985
1034
// set delay and max delay time exactly 1 render quantum
986
- {
987
- let sample_rate = 48000. ;
988
- let mut context = OfflineAudioContext :: new ( 1 , 256 , sample_rate) ;
1035
+ let sample_rate = 48000. ;
1036
+ let mut context = OfflineAudioContext :: new ( 1 , 256 , sample_rate) ;
989
1037
990
- let max_delay = 128. / sample_rate;
991
- let delay = context. create_delay ( max_delay. into ( ) ) ;
992
- delay. delay_time . set_value ( max_delay) ;
993
- delay. connect ( & context. destination ( ) ) ;
1038
+ let max_delay = 128. / sample_rate;
1039
+ let delay = context. create_delay ( max_delay. into ( ) ) ;
1040
+ delay. delay_time . set_value ( max_delay) ;
1041
+ delay. connect ( & context. destination ( ) ) ;
994
1042
995
- let mut dirac = context. create_buffer ( 1 , 1 , sample_rate) ;
996
- dirac. copy_to_channel ( & [ 1. ] , 0 ) ;
1043
+ let mut dirac = context. create_buffer ( 1 , 1 , sample_rate) ;
1044
+ dirac. copy_to_channel ( & [ 1. ] , 0 ) ;
997
1045
998
- let mut src = context. create_buffer_source ( ) ;
999
- src. connect ( & delay) ;
1000
- src. set_buffer ( dirac) ;
1001
- src. start_at ( 0. ) ;
1046
+ let mut src = context. create_buffer_source ( ) ;
1047
+ src. connect ( & delay) ;
1048
+ src. set_buffer ( dirac) ;
1049
+ src. start_at ( 0. ) ;
1002
1050
1003
- let result = context. start_rendering_sync ( ) ;
1004
- let channel = result. get_channel_data ( 0 ) ;
1051
+ let result = context. start_rendering_sync ( ) ;
1052
+ let channel = result. get_channel_data ( 0 ) ;
1005
1053
1006
- let mut expected = vec ! [ 0. ; 256 ] ;
1007
- expected[ 128 ] = 1. ;
1054
+ let mut expected = vec ! [ 0. ; 256 ] ;
1055
+ expected[ 128 ] = 1. ;
1008
1056
1009
- assert_float_eq ! ( channel[ ..] , expected[ ..] , abs_all <= 1e-5 ) ;
1010
- }
1057
+ assert_float_eq ! ( channel[ ..] , expected[ ..] , abs_all <= 1e-5 ) ;
1058
+ }
1011
1059
1060
+ #[ test]
1061
+ fn test_max_delay_multiple_of_quantum_size_2 ( ) {
1012
1062
// set delay and max delay time exactly 2 render quantum
1013
- {
1014
- let sample_rate = 48_000. ;
1015
- let mut context = OfflineAudioContext :: new ( 1 , 3 * 128 , sample_rate) ;
1063
+ let sample_rate = 48_000. ;
1064
+ let mut context = OfflineAudioContext :: new ( 1 , 3 * 128 , sample_rate) ;
1016
1065
1017
- let max_delay = 128. * 2. / sample_rate;
1018
- let delay = context. create_delay ( max_delay. into ( ) ) ;
1019
- delay. delay_time . set_value ( max_delay) ;
1020
- delay. connect ( & context. destination ( ) ) ;
1066
+ let max_delay = 128. * 2. / sample_rate;
1067
+ let delay = context. create_delay ( max_delay. into ( ) ) ;
1068
+ delay. delay_time . set_value ( max_delay) ;
1069
+ delay. connect ( & context. destination ( ) ) ;
1021
1070
1022
- let mut dirac = context. create_buffer ( 1 , 1 , sample_rate) ;
1023
- dirac. copy_to_channel ( & [ 1. ] , 0 ) ;
1071
+ let mut dirac = context. create_buffer ( 1 , 1 , sample_rate) ;
1072
+ dirac. copy_to_channel ( & [ 1. ] , 0 ) ;
1024
1073
1025
- let mut src = context. create_buffer_source ( ) ;
1026
- src. connect ( & delay) ;
1027
- src. set_buffer ( dirac) ;
1028
- src. start_at ( 0. ) ;
1074
+ let mut src = context. create_buffer_source ( ) ;
1075
+ src. connect ( & delay) ;
1076
+ src. set_buffer ( dirac) ;
1077
+ src. start_at ( 0. ) ;
1029
1078
1030
- let result = context. start_rendering_sync ( ) ;
1031
- let channel = result. get_channel_data ( 0 ) ;
1079
+ let result = context. start_rendering_sync ( ) ;
1080
+ let channel = result. get_channel_data ( 0 ) ;
1032
1081
1033
- let mut expected = vec ! [ 0. ; 3 * 128 ] ;
1034
- expected[ 256 ] = 1. ;
1082
+ let mut expected = vec ! [ 0. ; 3 * 128 ] ;
1083
+ expected[ 256 ] = 1. ;
1035
1084
1036
- assert_float_eq ! ( channel[ ..] , expected[ ..] , abs_all <= 1e-5 ) ;
1037
- }
1085
+ assert_float_eq ! ( channel[ ..] , expected[ ..] , abs_all <= 1e-5 ) ;
1038
1086
}
1039
1087
1040
1088
#[ test]
0 commit comments