@@ -7,6 +7,38 @@ use super::{
7
7
AudioNode , ChannelConfig , ChannelConfigOptions , ChannelCountMode , ChannelInterpretation ,
8
8
} ;
9
9
10
+ /// Assert that the channel count is valid for the ChannelMergerNode
11
+ /// see <https://webaudio.github.io/web-audio-api/#audionode-channelcount-constraints>
12
+ ///
13
+ /// # Panics
14
+ ///
15
+ /// This function panics if given count is greater than 2
16
+ ///
17
+ #[ track_caller]
18
+ #[ inline( always) ]
19
+ fn assert_valid_channel_count ( count : usize ) {
20
+ assert ! (
21
+ count == 1 ,
22
+ "InvalidStateError - channel count of ChannelMergerNode must be equal to 1"
23
+ ) ;
24
+ }
25
+
26
+ /// Assert that the channel count mode is valid for the ChannelMergerNode
27
+ /// see <https://webaudio.github.io/web-audio-api/#audionode-channelcountmode-constraints>
28
+ ///
29
+ /// # Panics
30
+ ///
31
+ /// This function panics if the mode is not equal to Explicit
32
+ ///
33
+ #[ track_caller]
34
+ #[ inline( always) ]
35
+ fn assert_valid_channel_count_mode ( mode : ChannelCountMode ) {
36
+ assert ! (
37
+ mode == ChannelCountMode :: Explicit ,
38
+ "InvalidStateError - channel count of ChannelMergerNode must be set to Explicit"
39
+ ) ;
40
+ }
41
+
10
42
/// Options for constructing a [`ChannelMergerNode`]
11
43
// dictionary ChannelMergerOptions : AudioNodeOptions {
12
44
// unsigned long numberOfInputs = 6;
@@ -34,6 +66,7 @@ impl Default for ChannelMergerOptions {
34
66
pub struct ChannelMergerNode {
35
67
registration : AudioContextRegistration ,
36
68
channel_config : ChannelConfig ,
69
+ number_of_inputs : usize ,
37
70
}
38
71
39
72
impl AudioNode for ChannelMergerNode {
@@ -45,16 +78,18 @@ impl AudioNode for ChannelMergerNode {
45
78
& self . channel_config
46
79
}
47
80
48
- fn set_channel_count ( & self , _v : usize ) {
49
- panic ! ( "InvalidStateError - Cannot edit channel count of ChannelMergerNode" )
81
+ fn set_channel_count ( & self , count : usize ) {
82
+ assert_valid_channel_count ( count) ;
83
+ self . channel_config . set_count ( count) ;
50
84
}
51
85
52
- fn set_channel_count_mode ( & self , _v : ChannelCountMode ) {
53
- panic ! ( "InvalidStateError - Cannot edit channel count mode of ChannelMergerNode" )
86
+ fn set_channel_count_mode ( & self , mode : ChannelCountMode ) {
87
+ assert_valid_channel_count_mode ( mode) ;
88
+ self . channel_config . set_count_mode ( mode) ;
54
89
}
55
90
56
91
fn number_of_inputs ( & self ) -> usize {
57
- self . channel_count ( )
92
+ self . number_of_inputs
58
93
}
59
94
60
95
fn number_of_outputs ( & self ) -> usize {
@@ -63,14 +98,17 @@ impl AudioNode for ChannelMergerNode {
63
98
}
64
99
65
100
impl ChannelMergerNode {
66
- pub fn new < C : BaseAudioContext > ( context : & C , mut options : ChannelMergerOptions ) -> Self {
101
+ pub fn new < C : BaseAudioContext > ( context : & C , options : ChannelMergerOptions ) -> Self {
67
102
context. register ( move |registration| {
68
103
crate :: assert_valid_number_of_channels ( options. number_of_inputs ) ;
69
- options. channel_config . count = options. number_of_inputs ;
104
+
105
+ assert_valid_channel_count ( options. channel_config . count ) ;
106
+ assert_valid_channel_count_mode ( options. channel_config . count_mode ) ;
70
107
71
108
let node = ChannelMergerNode {
72
109
registration,
73
110
channel_config : options. channel_config . into ( ) ,
111
+ number_of_inputs : options. number_of_inputs ,
74
112
} ;
75
113
76
114
let render = ChannelMergerRenderer { } ;
@@ -111,3 +149,78 @@ impl AudioProcessor for ChannelMergerRenderer {
111
149
false
112
150
}
113
151
}
152
+
153
+ #[ cfg( test) ]
154
+ mod tests {
155
+ use crate :: context:: { BaseAudioContext , OfflineAudioContext } ;
156
+ use crate :: node:: { AudioNode , AudioScheduledSourceNode } ;
157
+
158
+ use float_eq:: assert_float_eq;
159
+
160
+ #[ test]
161
+ fn test_merge ( ) {
162
+ let sample_rate = 48000. ;
163
+ let mut context = OfflineAudioContext :: new ( 2 , 128 , sample_rate) ;
164
+
165
+ let merger = context. create_channel_merger ( 2 ) ;
166
+ merger. connect ( & context. destination ( ) ) ;
167
+
168
+ let mut src1 = context. create_constant_source ( ) ;
169
+ src1. offset ( ) . set_value ( 2. ) ;
170
+ src1. connect_at ( & merger, 0 , 0 ) ;
171
+ src1. start ( ) ;
172
+
173
+ let mut src2 = context. create_constant_source ( ) ;
174
+ src2. offset ( ) . set_value ( 3. ) ;
175
+ src2. connect_at ( & merger, 0 , 1 ) ;
176
+ src2. start ( ) ;
177
+
178
+ let buffer = context. start_rendering_sync ( ) ;
179
+
180
+ let left = buffer. get_channel_data ( 0 ) ;
181
+ assert_float_eq ! ( left, & [ 2. ; 128 ] [ ..] , abs_all <= 0. ) ;
182
+
183
+ let right = buffer. get_channel_data ( 1 ) ;
184
+ assert_float_eq ! ( right, & [ 3. ; 128 ] [ ..] , abs_all <= 0. ) ;
185
+ }
186
+
187
+ #[ test]
188
+ fn test_merge_disconnect ( ) {
189
+ let sample_rate = 48000. ;
190
+ let length = 4 * 128 ;
191
+ let disconnect_at = length as f64 / sample_rate as f64 / 2. ;
192
+ let mut context = OfflineAudioContext :: new ( 2 , length, sample_rate) ;
193
+
194
+ let merger = context. create_channel_merger ( 2 ) ;
195
+ merger. connect ( & context. destination ( ) ) ;
196
+
197
+ let mut src1 = context. create_constant_source ( ) ;
198
+ src1. offset ( ) . set_value ( 2. ) ;
199
+ src1. connect_at ( & merger, 0 , 0 ) ;
200
+ src1. start ( ) ;
201
+
202
+ let mut src2 = context. create_constant_source ( ) ;
203
+ src2. offset ( ) . set_value ( 3. ) ;
204
+ src2. connect_at ( & merger, 0 , 1 ) ;
205
+ src2. start ( ) ;
206
+
207
+ context. suspend_sync ( disconnect_at, move |_| src2. disconnect ( ) ) ;
208
+
209
+ let buffer = context. start_rendering_sync ( ) ;
210
+
211
+ let left = buffer. get_channel_data ( 0 ) ;
212
+ assert_float_eq ! ( left, & vec![ 2. ; length] [ ..] , abs_all <= 0. ) ;
213
+
214
+ let right = buffer. get_channel_data ( 1 ) ;
215
+ assert_float_eq ! (
216
+ & right[ 0 ..length / 2 ] ,
217
+ & vec![ 3. ; length / 2 ] [ ..] ,
218
+ abs_all <= 0.
219
+ ) ;
220
+ assert_float_eq ! (
221
+ & right[ length / 2 ..] ,
222
+ & vec![ 0. ; length / 2 ] [ ..] ,
223
+ abs_all <= 0.
224
+ ) ;
225
+ }
226
+ }
0 commit comments