@@ -197,24 +197,20 @@ impl DelayNode {
197197 "NotSupportedError - maxDelayTime MUST be greater than zero and less than three minutes" ,
198198 ) ;
199199
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
203202 // 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)
206205 let quantum_duration = 1. / sample_rate * RENDER_QUANTUM_SIZE as f64 ;
207206 let max_delay_time = options. max_delay_time . max ( quantum_duration) ;
208207
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 ) ;
218214
219215 let shared_ring_buffer = Rc :: new ( RefCell :: new ( ring_buffer) ) ;
220216 let shared_ring_buffer_clone = Rc :: clone ( & shared_ring_buffer) ;
@@ -707,60 +703,59 @@ mod tests {
707703 }
708704
709705 #[ 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) ;
715710
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 ( ) ) ;
719714
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 ) ;
722717
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. ) ;
727722
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 ) ;
730725
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 ;
734729
735- assert_float_eq ! ( channel[ ..] , expected[ ..] , abs_all <= 0.00001 ) ;
736- }
730+ assert_float_eq ! ( channel[ ..] , expected[ ..] , abs_all <= 0.00001 ) ;
731+ }
737732
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) ;
742738
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 ( ) ) ;
746742
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 ) ;
749745
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. ) ;
754750
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 ) ;
757753
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 ;
761757
762- assert_float_eq ! ( channel[ ..] , expected[ ..] , abs_all <= 1e-5 ) ;
763- }
758+ assert_float_eq ! ( channel[ ..] , expected[ ..] , abs_all <= 1e-5 ) ;
764759 }
765760
766761 #[ test]
@@ -935,6 +930,60 @@ mod tests {
935930 assert_float_eq ! ( channel[ ..] , expected[ ..] , abs_all <= 0. ) ;
936931 }
937932
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+
938987 #[ test]
939988 fn test_max_delay_smaller_than_quantum_size ( ) {
940989 // regression test that even if the declared max_delay_time is smaller than
@@ -975,66 +1024,65 @@ mod tests {
9751024 }
9761025 }
9771026
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
9781032 #[ 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 ( ) {
9851034 // 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) ;
9891037
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 ( ) ) ;
9941042
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 ) ;
9971045
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. ) ;
10021050
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 ) ;
10051053
1006- let mut expected = vec ! [ 0. ; 256 ] ;
1007- expected[ 128 ] = 1. ;
1054+ let mut expected = vec ! [ 0. ; 256 ] ;
1055+ expected[ 128 ] = 1. ;
10081056
1009- assert_float_eq ! ( channel[ ..] , expected[ ..] , abs_all <= 1e-5 ) ;
1010- }
1057+ assert_float_eq ! ( channel[ ..] , expected[ ..] , abs_all <= 1e-5 ) ;
1058+ }
10111059
1060+ #[ test]
1061+ fn test_max_delay_multiple_of_quantum_size_2 ( ) {
10121062 // 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) ;
10161065
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 ( ) ) ;
10211070
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 ) ;
10241073
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. ) ;
10291078
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 ) ;
10321081
1033- let mut expected = vec ! [ 0. ; 3 * 128 ] ;
1034- expected[ 256 ] = 1. ;
1082+ let mut expected = vec ! [ 0. ; 3 * 128 ] ;
1083+ expected[ 256 ] = 1. ;
10351084
1036- assert_float_eq ! ( channel[ ..] , expected[ ..] , abs_all <= 1e-5 ) ;
1037- }
1085+ assert_float_eq ! ( channel[ ..] , expected[ ..] , abs_all <= 1e-5 ) ;
10381086 }
10391087
10401088 #[ test]
0 commit comments