amine@173
|
1 """
|
amine@172
|
2 @author: Amine Sehili <amine.sehili@gmail.com>
|
amine@172
|
3 September 2015
|
amine@172
|
4
|
amine@173
|
5 """
|
amine@172
|
6
|
amine@172
|
7 import unittest
|
amine@172
|
8 from functools import partial
|
amine@172
|
9 import sys
|
amine@173
|
10 from auditok import (
|
amine@173
|
11 dataset,
|
amine@173
|
12 ADSFactory,
|
amine@173
|
13 AudioDataSource,
|
amine@173
|
14 BufferAudioSource,
|
amine@173
|
15 WaveAudioSource,
|
amine@173
|
16 DuplicateArgument,
|
amine@173
|
17 )
|
amine@172
|
18 import wave
|
amine@172
|
19
|
amine@172
|
20
|
amine@172
|
21 try:
|
amine@172
|
22 from builtins import range
|
amine@172
|
23 except ImportError:
|
amine@172
|
24 if sys.version_info < (3, 0):
|
amine@172
|
25 range = xrange
|
amine@172
|
26
|
amine@173
|
27
|
amine@172
|
28 class TestADSFactoryFileAudioSource(unittest.TestCase):
|
amine@172
|
29 def setUp(self):
|
amine@173
|
30 self.audio_source = WaveAudioSource(
|
amine@173
|
31 filename=dataset.one_to_six_arabic_16000_mono_bc_noise
|
amine@173
|
32 )
|
amine@173
|
33
|
amine@172
|
34 def test_ADS_type(self):
|
amine@173
|
35
|
amine@172
|
36 ads = ADSFactory.ads(audio_source=self.audio_source)
|
amine@173
|
37
|
amine@173
|
38 self.assertIsInstance(
|
amine@173
|
39 ads,
|
amine@173
|
40 AudioDataSource,
|
amine@173
|
41 msg="wrong type for ads object, expected: 'AudioDataSource', found: {0}".format(
|
amine@173
|
42 type(ads)
|
amine@173
|
43 ),
|
amine@173
|
44 )
|
amine@173
|
45
|
amine@172
|
46 def test_default_block_size(self):
|
amine@172
|
47 ads = ADSFactory.ads(audio_source=self.audio_source)
|
amine@173
|
48 size = ads.block_size
|
amine@173
|
49 self.assertEqual(
|
amine@173
|
50 size,
|
amine@173
|
51 160,
|
amine@173
|
52 "Wrong default block_size, expected: 160, found: {0}".format(size),
|
amine@173
|
53 )
|
amine@173
|
54
|
amine@172
|
55 def test_block_size(self):
|
amine@172
|
56 ads = ADSFactory.ads(audio_source=self.audio_source, block_size=512)
|
amine@173
|
57 size = ads.block_size
|
amine@173
|
58 self.assertEqual(
|
amine@173
|
59 size,
|
amine@173
|
60 512,
|
amine@173
|
61 "Wrong block_size, expected: 512, found: {0}".format(size),
|
amine@173
|
62 )
|
amine@173
|
63
|
amine@172
|
64 # with alias keyword
|
amine@172
|
65 ads = ADSFactory.ads(audio_source=self.audio_source, bs=160)
|
amine@173
|
66 size = ads.block_size
|
amine@173
|
67 self.assertEqual(
|
amine@173
|
68 size,
|
amine@173
|
69 160,
|
amine@173
|
70 "Wrong block_size, expected: 160, found: {0}".format(size),
|
amine@173
|
71 )
|
amine@173
|
72
|
amine@172
|
73 def test_block_duration(self):
|
amine@173
|
74
|
amine@173
|
75 ads = ADSFactory.ads(
|
amine@173
|
76 audio_source=self.audio_source, block_dur=0.01
|
amine@173
|
77 ) # 10 ms
|
amine@173
|
78 size = ads.block_size
|
amine@173
|
79 self.assertEqual(
|
amine@173
|
80 size,
|
amine@173
|
81 160,
|
amine@173
|
82 "Wrong block_size, expected: 160, found: {0}".format(size),
|
amine@173
|
83 )
|
amine@173
|
84
|
amine@172
|
85 # with alias keyword
|
amine@173
|
86 ads = ADSFactory.ads(audio_source=self.audio_source, bd=0.025) # 25 ms
|
amine@173
|
87 size = ads.block_size
|
amine@173
|
88 self.assertEqual(
|
amine@173
|
89 size,
|
amine@173
|
90 400,
|
amine@173
|
91 "Wrong block_size, expected: 400, found: {0}".format(size),
|
amine@173
|
92 )
|
amine@173
|
93
|
amine@172
|
94 def test_hop_duration(self):
|
amine@173
|
95
|
amine@173
|
96 ads = ADSFactory.ads(
|
amine@173
|
97 audio_source=self.audio_source, block_dur=0.02, hop_dur=0.01
|
amine@173
|
98 ) # 10 ms
|
amine@172
|
99 size = ads.hop_size
|
amine@173
|
100 self.assertEqual(
|
amine@173
|
101 size, 160, "Wrong hop_size, expected: 160, found: {0}".format(size)
|
amine@173
|
102 )
|
amine@173
|
103
|
amine@172
|
104 # with alias keyword
|
amine@173
|
105 ads = ADSFactory.ads(
|
amine@173
|
106 audio_source=self.audio_source, bd=0.025, hop_dur=0.015
|
amine@173
|
107 ) # 15 ms
|
amine@172
|
108 size = ads.hop_size
|
amine@173
|
109 self.assertEqual(
|
amine@173
|
110 size,
|
amine@173
|
111 240,
|
amine@173
|
112 "Wrong block_size, expected: 240, found: {0}".format(size),
|
amine@173
|
113 )
|
amine@173
|
114
|
amine@172
|
115 def test_sampling_rate(self):
|
amine@172
|
116 ads = ADSFactory.ads(audio_source=self.audio_source)
|
amine@173
|
117
|
amine@173
|
118 srate = ads.sampling_rate
|
amine@173
|
119 self.assertEqual(
|
amine@173
|
120 srate,
|
amine@173
|
121 16000,
|
amine@173
|
122 "Wrong sampling rate, expected: 16000, found: {0}".format(srate),
|
amine@173
|
123 )
|
amine@173
|
124
|
amine@172
|
125 def test_sample_width(self):
|
amine@172
|
126 ads = ADSFactory.ads(audio_source=self.audio_source)
|
amine@173
|
127
|
amine@173
|
128 swidth = ads.sample_width
|
amine@173
|
129 self.assertEqual(
|
amine@173
|
130 swidth,
|
amine@173
|
131 2,
|
amine@173
|
132 "Wrong sample width, expected: 2, found: {0}".format(swidth),
|
amine@173
|
133 )
|
amine@173
|
134
|
amine@172
|
135 def test_channels(self):
|
amine@172
|
136 ads = ADSFactory.ads(audio_source=self.audio_source)
|
amine@173
|
137
|
amine@173
|
138 channels = ads.channels
|
amine@173
|
139 self.assertEqual(
|
amine@173
|
140 channels,
|
amine@173
|
141 1,
|
amine@173
|
142 "Wrong number of channels, expected: 1, found: {0}".format(
|
amine@173
|
143 channels
|
amine@173
|
144 ),
|
amine@173
|
145 )
|
amine@173
|
146
|
amine@172
|
147 def test_read(self):
|
amine@173
|
148 ads = ADSFactory.ads(audio_source=self.audio_source, block_size=256)
|
amine@173
|
149
|
amine@172
|
150 ads.open()
|
amine@172
|
151 ads_data = ads.read()
|
amine@172
|
152 ads.close()
|
amine@173
|
153
|
amine@173
|
154 audio_source = WaveAudioSource(
|
amine@173
|
155 filename=dataset.one_to_six_arabic_16000_mono_bc_noise
|
amine@173
|
156 )
|
amine@172
|
157 audio_source.open()
|
amine@172
|
158 audio_source_data = audio_source.read(256)
|
amine@172
|
159 audio_source.close()
|
amine@173
|
160
|
amine@173
|
161 self.assertEqual(
|
amine@173
|
162 ads_data, audio_source_data, "Unexpected data read from ads"
|
amine@173
|
163 )
|
amine@173
|
164
|
amine@172
|
165 def test_Limiter_Deco_read(self):
|
amine@172
|
166 # read a maximum of 0.75 seconds from audio source
|
amine@172
|
167 ads = ADSFactory.ads(audio_source=self.audio_source, max_time=0.75)
|
amine@173
|
168
|
amine@172
|
169 ads_data = []
|
amine@172
|
170 ads.open()
|
amine@172
|
171 while True:
|
amine@172
|
172 block = ads.read()
|
amine@172
|
173 if block is None:
|
amine@172
|
174 break
|
amine@172
|
175 ads_data.append(block)
|
amine@172
|
176 ads.close()
|
amine@173
|
177 ads_data = b"".join(ads_data)
|
amine@173
|
178
|
amine@173
|
179 audio_source = WaveAudioSource(
|
amine@173
|
180 filename=dataset.one_to_six_arabic_16000_mono_bc_noise
|
amine@173
|
181 )
|
amine@172
|
182 audio_source.open()
|
amine@172
|
183 audio_source_data = audio_source.read(int(16000 * 0.75))
|
amine@172
|
184 audio_source.close()
|
amine@173
|
185
|
amine@173
|
186 self.assertEqual(
|
amine@173
|
187 ads_data, audio_source_data, "Unexpected data read from LimiterADS"
|
amine@173
|
188 )
|
amine@173
|
189
|
amine@172
|
190 def test_Limiter_Deco_read_limit(self):
|
amine@173
|
191 # read a maximum of 1.191 seconds from audio source
|
amine@172
|
192 ads = ADSFactory.ads(audio_source=self.audio_source, max_time=1.191)
|
amine@173
|
193 total_samples = round(ads.sampling_rate * 1.191)
|
amine@173
|
194 nb_full_blocks, last_block_size = divmod(total_samples, ads.block_size)
|
amine@173
|
195 total_samples_with_overlap = (
|
amine@173
|
196 nb_full_blocks * ads.block_size + last_block_size
|
amine@173
|
197 )
|
amine@173
|
198 expected_read_bytes = (
|
amine@173
|
199 total_samples_with_overlap * ads.sw * ads.channels
|
amine@173
|
200 )
|
amine@173
|
201
|
amine@172
|
202 total_read = 0
|
amine@172
|
203 ads.open()
|
amine@172
|
204 i = 0
|
amine@172
|
205 while True:
|
amine@172
|
206 block = ads.read()
|
amine@172
|
207 if block is None:
|
amine@172
|
208 break
|
amine@172
|
209 i += 1
|
amine@172
|
210 total_read += len(block)
|
amine@173
|
211
|
amine@172
|
212 ads.close()
|
amine@173
|
213
|
amine@173
|
214 self.assertEqual(
|
amine@173
|
215 total_read,
|
amine@173
|
216 expected_read_bytes,
|
amine@173
|
217 "Wrong data length read from LimiterADS, expected: {0}, found: {1}".format(
|
amine@173
|
218 expected_read_bytes, total_read
|
amine@173
|
219 ),
|
amine@173
|
220 )
|
amine@173
|
221
|
amine@172
|
222 def test_Recorder_Deco_read(self):
|
amine@173
|
223 ads = ADSFactory.ads(
|
amine@173
|
224 audio_source=self.audio_source, record=True, block_size=500
|
amine@173
|
225 )
|
amine@173
|
226
|
amine@172
|
227 ads_data = []
|
amine@172
|
228 ads.open()
|
amine@172
|
229 for i in range(10):
|
amine@172
|
230 block = ads.read()
|
amine@172
|
231 if block is None:
|
amine@172
|
232 break
|
amine@172
|
233 ads_data.append(block)
|
amine@172
|
234 ads.close()
|
amine@173
|
235 ads_data = b"".join(ads_data)
|
amine@173
|
236
|
amine@173
|
237 audio_source = WaveAudioSource(
|
amine@173
|
238 filename=dataset.one_to_six_arabic_16000_mono_bc_noise
|
amine@173
|
239 )
|
amine@172
|
240 audio_source.open()
|
amine@172
|
241 audio_source_data = audio_source.read(500 * 10)
|
amine@172
|
242 audio_source.close()
|
amine@173
|
243
|
amine@173
|
244 self.assertEqual(
|
amine@173
|
245 ads_data,
|
amine@173
|
246 audio_source_data,
|
amine@173
|
247 "Unexpected data read from RecorderADS",
|
amine@173
|
248 )
|
amine@173
|
249
|
amine@172
|
250 def test_Recorder_Deco_is_rewindable(self):
|
amine@172
|
251 ads = ADSFactory.ads(audio_source=self.audio_source, record=True)
|
amine@173
|
252
|
amine@173
|
253 self.assertTrue(
|
amine@173
|
254 ads.rewindable, "RecorderADS.is_rewindable should return True"
|
amine@173
|
255 )
|
amine@173
|
256
|
amine@172
|
257 def test_Recorder_Deco_rewind_and_read(self):
|
amine@173
|
258 ads = ADSFactory.ads(
|
amine@173
|
259 audio_source=self.audio_source, record=True, block_size=320
|
amine@173
|
260 )
|
amine@173
|
261
|
amine@172
|
262 ads.open()
|
amine@172
|
263 for i in range(10):
|
amine@172
|
264 ads.read()
|
amine@173
|
265
|
amine@172
|
266 ads.rewind()
|
amine@173
|
267
|
amine@172
|
268 # read all available data after rewind
|
amine@172
|
269 ads_data = []
|
amine@172
|
270 while True:
|
amine@172
|
271 block = ads.read()
|
amine@172
|
272 if block is None:
|
amine@172
|
273 break
|
amine@172
|
274 ads_data.append(block)
|
amine@172
|
275 ads.close()
|
amine@173
|
276 ads_data = b"".join(ads_data)
|
amine@173
|
277
|
amine@173
|
278 audio_source = WaveAudioSource(
|
amine@173
|
279 filename=dataset.one_to_six_arabic_16000_mono_bc_noise
|
amine@173
|
280 )
|
amine@172
|
281 audio_source.open()
|
amine@172
|
282 audio_source_data = audio_source.read(320 * 10)
|
amine@172
|
283 audio_source.close()
|
amine@173
|
284
|
amine@173
|
285 self.assertEqual(
|
amine@173
|
286 ads_data,
|
amine@173
|
287 audio_source_data,
|
amine@173
|
288 "Unexpected data read from RecorderADS",
|
amine@173
|
289 )
|
amine@173
|
290
|
amine@172
|
291 def test_Overlap_Deco_read(self):
|
amine@173
|
292
|
amine@172
|
293 # Use arbitrary valid block_size and hop_size
|
amine@172
|
294 block_size = 1714
|
amine@172
|
295 hop_size = 313
|
amine@173
|
296
|
amine@173
|
297 ads = ADSFactory.ads(
|
amine@173
|
298 audio_source=self.audio_source,
|
amine@173
|
299 block_size=block_size,
|
amine@173
|
300 hop_size=hop_size,
|
amine@173
|
301 )
|
amine@173
|
302
|
amine@172
|
303 # Read all available data overlapping blocks
|
amine@172
|
304 ads.open()
|
amine@172
|
305 ads_data = []
|
amine@172
|
306 while True:
|
amine@172
|
307 block = ads.read()
|
amine@172
|
308 if block is None:
|
amine@172
|
309 break
|
amine@172
|
310 ads_data.append(block)
|
amine@172
|
311 ads.close()
|
amine@173
|
312
|
amine@172
|
313 # Read all data from file and build a BufferAudioSource
|
amine@172
|
314 fp = wave.open(dataset.one_to_six_arabic_16000_mono_bc_noise, "r")
|
amine@172
|
315 wave_data = fp.readframes(fp.getnframes())
|
amine@172
|
316 fp.close()
|
amine@173
|
317 audio_source = BufferAudioSource(
|
amine@173
|
318 wave_data, ads.sampling_rate, ads.sample_width, ads.channels
|
amine@173
|
319 )
|
amine@172
|
320 audio_source.open()
|
amine@173
|
321
|
amine@172
|
322 # Compare all blocks read from OverlapADS to those read
|
amine@216
|
323 # from an audio source with a manual position setting
|
amine@173
|
324 for i, block in enumerate(ads_data):
|
amine@173
|
325
|
amine@172
|
326 tmp = audio_source.read(block_size)
|
amine@173
|
327
|
amine@173
|
328 self.assertEqual(
|
amine@173
|
329 block,
|
amine@173
|
330 tmp,
|
amine@173
|
331 "Unexpected block (N={0}) read from OverlapADS".format(i),
|
amine@173
|
332 )
|
amine@173
|
333
|
amine@216
|
334 audio_source.position = (i + 1) * hop_size
|
amine@173
|
335
|
amine@172
|
336 audio_source.close()
|
amine@173
|
337
|
amine@173
|
338 def test_Limiter_Overlap_Deco_read(self):
|
amine@173
|
339
|
amine@172
|
340 block_size = 256
|
amine@172
|
341 hop_size = 200
|
amine@173
|
342
|
amine@173
|
343 ads = ADSFactory.ads(
|
amine@173
|
344 audio_source=self.audio_source,
|
amine@173
|
345 max_time=0.50,
|
amine@173
|
346 block_size=block_size,
|
amine@173
|
347 hop_size=hop_size,
|
amine@173
|
348 )
|
amine@173
|
349
|
amine@172
|
350 # Read all available data overlapping blocks
|
amine@172
|
351 ads.open()
|
amine@172
|
352 ads_data = []
|
amine@172
|
353 while True:
|
amine@172
|
354 block = ads.read()
|
amine@172
|
355 if block is None:
|
amine@172
|
356 break
|
amine@172
|
357 ads_data.append(block)
|
amine@172
|
358 ads.close()
|
amine@173
|
359
|
amine@172
|
360 # Read all data from file and build a BufferAudioSource
|
amine@172
|
361 fp = wave.open(dataset.one_to_six_arabic_16000_mono_bc_noise, "r")
|
amine@172
|
362 wave_data = fp.readframes(fp.getnframes())
|
amine@172
|
363 fp.close()
|
amine@173
|
364 audio_source = BufferAudioSource(
|
amine@173
|
365 wave_data, ads.sampling_rate, ads.sample_width, ads.channels
|
amine@173
|
366 )
|
amine@172
|
367 audio_source.open()
|
amine@173
|
368
|
amine@172
|
369 # Compare all blocks read from OverlapADS to those read
|
amine@216
|
370 # from an audio source with a manual position setting
|
amine@173
|
371 for i, block in enumerate(ads_data):
|
amine@173
|
372 tmp = audio_source.read(len(block) // (ads.sw * ads.ch))
|
amine@173
|
373 self.assertEqual(
|
amine@173
|
374 len(block),
|
amine@173
|
375 len(tmp),
|
amine@173
|
376 "Unexpected block (N={0}) read from OverlapADS".format(i),
|
amine@173
|
377 )
|
amine@216
|
378 audio_source.position = (i + 1) * hop_size
|
amine@173
|
379
|
amine@172
|
380 audio_source.close()
|
amine@173
|
381
|
amine@172
|
382 def test_Limiter_Overlap_Deco_read_limit(self):
|
amine@173
|
383
|
amine@172
|
384 block_size = 313
|
amine@172
|
385 hop_size = 207
|
amine@173
|
386 ads = ADSFactory.ads(
|
amine@173
|
387 audio_source=self.audio_source,
|
amine@173
|
388 max_time=1.932,
|
amine@173
|
389 block_size=block_size,
|
amine@173
|
390 hop_size=hop_size,
|
amine@173
|
391 )
|
amine@173
|
392
|
amine@173
|
393 total_samples = round(ads.sampling_rate * 1.932)
|
amine@173
|
394 first_read_size = block_size
|
amine@173
|
395 next_read_size = block_size - hop_size
|
amine@173
|
396 nb_next_blocks, last_block_size = divmod(
|
amine@173
|
397 (total_samples - first_read_size), next_read_size
|
amine@173
|
398 )
|
amine@173
|
399 total_samples_with_overlap = (
|
amine@173
|
400 first_read_size + next_read_size * nb_next_blocks + last_block_size
|
amine@173
|
401 )
|
amine@173
|
402 expected_read_bytes = (
|
amine@173
|
403 total_samples_with_overlap * ads.sw * ads.channels
|
amine@173
|
404 )
|
amine@173
|
405
|
amine@173
|
406 cache_size = (block_size - hop_size) * ads.sample_width * ads.channels
|
amine@172
|
407 total_read = cache_size
|
amine@173
|
408
|
amine@172
|
409 ads.open()
|
amine@172
|
410 i = 0
|
amine@172
|
411 while True:
|
amine@172
|
412 block = ads.read()
|
amine@172
|
413 if block is None:
|
amine@172
|
414 break
|
amine@172
|
415 i += 1
|
amine@172
|
416 total_read += len(block) - cache_size
|
amine@173
|
417
|
amine@172
|
418 ads.close()
|
amine@173
|
419 self.assertEqual(
|
amine@173
|
420 total_read,
|
amine@173
|
421 expected_read_bytes,
|
amine@173
|
422 "Wrong data length read from LimiterADS, expected: {0}, found: {1}".format(
|
amine@173
|
423 expected_read_bytes, total_read
|
amine@173
|
424 ),
|
amine@173
|
425 )
|
amine@173
|
426
|
amine@172
|
427 def test_Recorder_Overlap_Deco_is_rewindable(self):
|
amine@173
|
428 ads = ADSFactory.ads(
|
amine@173
|
429 audio_source=self.audio_source,
|
amine@173
|
430 block_size=320,
|
amine@173
|
431 hop_size=160,
|
amine@173
|
432 record=True,
|
amine@173
|
433 )
|
amine@173
|
434 self.assertTrue(
|
amine@173
|
435 ads.rewindable, "RecorderADS.is_rewindable should return True"
|
amine@173
|
436 )
|
amine@172
|
437
|
amine@172
|
438 def test_Recorder_Overlap_Deco_rewind_and_read(self):
|
amine@173
|
439
|
amine@172
|
440 # Use arbitrary valid block_size and hop_size
|
amine@172
|
441 block_size = 1600
|
amine@172
|
442 hop_size = 400
|
amine@173
|
443
|
amine@173
|
444 ads = ADSFactory.ads(
|
amine@173
|
445 audio_source=self.audio_source,
|
amine@173
|
446 block_size=block_size,
|
amine@173
|
447 hop_size=hop_size,
|
amine@173
|
448 record=True,
|
amine@173
|
449 )
|
amine@173
|
450
|
amine@172
|
451 # Read all available data overlapping blocks
|
amine@172
|
452 ads.open()
|
amine@172
|
453 i = 0
|
amine@172
|
454 while True:
|
amine@172
|
455 block = ads.read()
|
amine@172
|
456 if block is None:
|
amine@172
|
457 break
|
amine@172
|
458 i += 1
|
amine@173
|
459
|
amine@172
|
460 ads.rewind()
|
amine@173
|
461
|
amine@172
|
462 # Read all data from file and build a BufferAudioSource
|
amine@172
|
463 fp = wave.open(dataset.one_to_six_arabic_16000_mono_bc_noise, "r")
|
amine@172
|
464 wave_data = fp.readframes(fp.getnframes())
|
amine@172
|
465 fp.close()
|
amine@173
|
466 audio_source = BufferAudioSource(
|
amine@173
|
467 wave_data, ads.sampling_rate, ads.sample_width, ads.channels
|
amine@173
|
468 )
|
amine@172
|
469 audio_source.open()
|
amine@173
|
470
|
amine@172
|
471 # Compare all blocks read from OverlapADS to those read
|
amine@216
|
472 # from an audio source with a manual position setting
|
amine@172
|
473 for j in range(i):
|
amine@173
|
474
|
amine@172
|
475 tmp = audio_source.read(block_size)
|
amine@173
|
476
|
amine@173
|
477 self.assertEqual(
|
amine@173
|
478 ads.read(),
|
amine@173
|
479 tmp,
|
amine@173
|
480 "Unexpected block (N={0}) read from OverlapADS".format(i),
|
amine@173
|
481 )
|
amine@216
|
482 audio_source.position = (j + 1) * hop_size
|
amine@173
|
483
|
amine@172
|
484 ads.close()
|
amine@172
|
485 audio_source.close()
|
amine@173
|
486
|
amine@172
|
487 def test_Limiter_Recorder_Overlap_Deco_rewind_and_read(self):
|
amine@173
|
488
|
amine@172
|
489 # Use arbitrary valid block_size and hop_size
|
amine@172
|
490 block_size = 1600
|
amine@172
|
491 hop_size = 400
|
amine@173
|
492
|
amine@173
|
493 ads = ADSFactory.ads(
|
amine@173
|
494 audio_source=self.audio_source,
|
amine@173
|
495 max_time=1.50,
|
amine@173
|
496 block_size=block_size,
|
amine@173
|
497 hop_size=hop_size,
|
amine@173
|
498 record=True,
|
amine@173
|
499 )
|
amine@173
|
500
|
amine@172
|
501 # Read all available data overlapping blocks
|
amine@172
|
502 ads.open()
|
amine@172
|
503 i = 0
|
amine@172
|
504 while True:
|
amine@172
|
505 block = ads.read()
|
amine@172
|
506 if block is None:
|
amine@172
|
507 break
|
amine@172
|
508 i += 1
|
amine@173
|
509
|
amine@172
|
510 ads.rewind()
|
amine@173
|
511
|
amine@172
|
512 # Read all data from file and build a BufferAudioSource
|
amine@172
|
513 fp = wave.open(dataset.one_to_six_arabic_16000_mono_bc_noise, "r")
|
amine@172
|
514 wave_data = fp.readframes(fp.getnframes())
|
amine@172
|
515 fp.close()
|
amine@173
|
516 audio_source = BufferAudioSource(
|
amine@173
|
517 wave_data, ads.sampling_rate, ads.sample_width, ads.channels
|
amine@173
|
518 )
|
amine@172
|
519 audio_source.open()
|
amine@173
|
520
|
amine@172
|
521 # Compare all blocks read from OverlapADS to those read
|
amine@216
|
522 # from an audio source with a manual position setting
|
amine@172
|
523 for j in range(i):
|
amine@173
|
524
|
amine@172
|
525 tmp = audio_source.read(block_size)
|
amine@173
|
526
|
amine@173
|
527 self.assertEqual(
|
amine@173
|
528 ads.read(),
|
amine@173
|
529 tmp,
|
amine@173
|
530 "Unexpected block (N={0}) read from OverlapADS".format(i),
|
amine@173
|
531 )
|
amine@216
|
532 audio_source.position = (j + 1) * hop_size
|
amine@173
|
533
|
amine@172
|
534 ads.close()
|
amine@172
|
535 audio_source.close()
|
amine@173
|
536
|
amine@172
|
537 def test_Limiter_Recorder_Overlap_Deco_rewind_and_read_limit(self):
|
amine@173
|
538
|
amine@172
|
539 # Use arbitrary valid block_size and hop_size
|
amine@172
|
540 block_size = 1000
|
amine@172
|
541 hop_size = 200
|
amine@173
|
542
|
amine@173
|
543 ads = ADSFactory.ads(
|
amine@173
|
544 audio_source=self.audio_source,
|
amine@173
|
545 max_time=1.317,
|
amine@173
|
546 block_size=block_size,
|
amine@173
|
547 hop_size=hop_size,
|
amine@173
|
548 record=True,
|
amine@173
|
549 )
|
amine@173
|
550 total_samples = round(ads.sampling_rate * 1.317)
|
amine@173
|
551 first_read_size = block_size
|
amine@173
|
552 next_read_size = block_size - hop_size
|
amine@173
|
553 nb_next_blocks, last_block_size = divmod(
|
amine@173
|
554 (total_samples - first_read_size), next_read_size
|
amine@173
|
555 )
|
amine@173
|
556 total_samples_with_overlap = (
|
amine@173
|
557 first_read_size + next_read_size * nb_next_blocks + last_block_size
|
amine@173
|
558 )
|
amine@173
|
559 expected_read_bytes = (
|
amine@173
|
560 total_samples_with_overlap * ads.sw * ads.channels
|
amine@173
|
561 )
|
amine@173
|
562
|
amine@173
|
563 cache_size = (block_size - hop_size) * ads.sample_width * ads.channels
|
amine@172
|
564 total_read = cache_size
|
amine@173
|
565
|
amine@172
|
566 ads.open()
|
amine@172
|
567 i = 0
|
amine@172
|
568 while True:
|
amine@172
|
569 block = ads.read()
|
amine@172
|
570 if block is None:
|
amine@172
|
571 break
|
amine@172
|
572 i += 1
|
amine@172
|
573 total_read += len(block) - cache_size
|
amine@173
|
574
|
amine@172
|
575 ads.close()
|
amine@173
|
576 self.assertEqual(
|
amine@173
|
577 total_read,
|
amine@173
|
578 expected_read_bytes,
|
amine@173
|
579 "Wrong data length read from LimiterADS, expected: {0}, found: {1}".format(
|
amine@173
|
580 expected_read_bytes, total_read
|
amine@173
|
581 ),
|
amine@173
|
582 )
|
amine@173
|
583
|
amine@173
|
584
|
amine@172
|
585 class TestADSFactoryBufferAudioSource(unittest.TestCase):
|
amine@172
|
586 def setUp(self):
|
amine@173
|
587 self.signal = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ012345"
|
amine@173
|
588 self.ads = ADSFactory.ads(
|
amine@173
|
589 data_buffer=self.signal,
|
amine@173
|
590 sampling_rate=16,
|
amine@173
|
591 sample_width=2,
|
amine@173
|
592 channels=1,
|
amine@218
|
593 block_size=4,
|
amine@173
|
594 )
|
amine@173
|
595
|
amine@172
|
596 def test_ADS_BAS_sampling_rate(self):
|
amine@173
|
597 srate = self.ads.sampling_rate
|
amine@173
|
598 self.assertEqual(
|
amine@173
|
599 srate,
|
amine@173
|
600 16,
|
amine@173
|
601 "Wrong sampling rate, expected: 16000, found: {0}".format(srate),
|
amine@173
|
602 )
|
amine@173
|
603
|
amine@172
|
604 def test_ADS_BAS_get_sample_width(self):
|
amine@173
|
605 swidth = self.ads.sample_width
|
amine@173
|
606 self.assertEqual(
|
amine@173
|
607 swidth,
|
amine@173
|
608 2,
|
amine@173
|
609 "Wrong sample width, expected: 2, found: {0}".format(swidth),
|
amine@173
|
610 )
|
amine@173
|
611
|
amine@172
|
612 def test_ADS_BAS_get_channels(self):
|
amine@173
|
613 channels = self.ads.channels
|
amine@173
|
614 self.assertEqual(
|
amine@173
|
615 channels,
|
amine@173
|
616 1,
|
amine@173
|
617 "Wrong number of channels, expected: 1, found: {0}".format(
|
amine@173
|
618 channels
|
amine@173
|
619 ),
|
amine@173
|
620 )
|
amine@173
|
621
|
amine@172
|
622 def test_Limiter_Recorder_Overlap_Deco_rewind_and_read(self):
|
amine@173
|
623
|
amine@172
|
624 # Use arbitrary valid block_size and hop_size
|
amine@172
|
625 block_size = 5
|
amine@172
|
626 hop_size = 4
|
amine@173
|
627
|
amine@173
|
628 ads = ADSFactory.ads(
|
amine@173
|
629 data_buffer=self.signal,
|
amine@173
|
630 sampling_rate=16,
|
amine@173
|
631 sample_width=2,
|
amine@173
|
632 channels=1,
|
amine@173
|
633 max_time=0.80,
|
amine@173
|
634 block_size=block_size,
|
amine@173
|
635 hop_size=hop_size,
|
amine@173
|
636 record=True,
|
amine@173
|
637 )
|
amine@173
|
638
|
amine@172
|
639 # Read all available data overlapping blocks
|
amine@172
|
640 ads.open()
|
amine@172
|
641 i = 0
|
amine@172
|
642 while True:
|
amine@172
|
643 block = ads.read()
|
amine@172
|
644 if block is None:
|
amine@172
|
645 break
|
amine@172
|
646 i += 1
|
amine@173
|
647
|
amine@172
|
648 ads.rewind()
|
amine@173
|
649
|
amine@172
|
650 # Build a BufferAudioSource
|
amine@173
|
651 audio_source = BufferAudioSource(
|
amine@173
|
652 self.signal, ads.sampling_rate, ads.sample_width, ads.channels
|
amine@173
|
653 )
|
amine@172
|
654 audio_source.open()
|
amine@173
|
655
|
amine@172
|
656 # Compare all blocks read from OverlapADS to those read
|
amine@216
|
657 # from an audio source with a manual position setting
|
amine@172
|
658 for j in range(i):
|
amine@173
|
659
|
amine@172
|
660 tmp = audio_source.read(block_size)
|
amine@173
|
661
|
amine@172
|
662 block = ads.read()
|
amine@173
|
663
|
amine@173
|
664 self.assertEqual(
|
amine@173
|
665 block,
|
amine@173
|
666 tmp,
|
amine@173
|
667 "Unexpected block '{}' (N={}) read from OverlapADS".format(
|
amine@173
|
668 block, i
|
amine@173
|
669 ),
|
amine@173
|
670 )
|
amine@216
|
671 audio_source.position = (j + 1) * hop_size
|
amine@173
|
672
|
amine@172
|
673 ads.close()
|
amine@172
|
674 audio_source.close()
|
amine@172
|
675
|
amine@172
|
676
|
amine@172
|
677 class TestADSFactoryAlias(unittest.TestCase):
|
amine@172
|
678 def setUp(self):
|
amine@172
|
679 self.signal = "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345"
|
amine@173
|
680
|
amine@172
|
681 def test_sampling_rate_alias(self):
|
amine@173
|
682 ads = ADSFactory.ads(
|
amine@218
|
683 data_buffer=self.signal,
|
amine@218
|
684 sr=16,
|
amine@218
|
685 sample_width=2,
|
amine@218
|
686 channels=1,
|
amine@218
|
687 block_dur=0.5,
|
amine@173
|
688 )
|
amine@173
|
689 srate = ads.sampling_rate
|
amine@173
|
690 self.assertEqual(
|
amine@173
|
691 srate,
|
amine@173
|
692 16,
|
amine@173
|
693 "Wrong sampling rate, expected: 16000, found: {0}".format(srate),
|
amine@173
|
694 )
|
amine@173
|
695
|
amine@172
|
696 def test_sampling_rate_duplicate(self):
|
amine@173
|
697 func = partial(
|
amine@173
|
698 ADSFactory.ads,
|
amine@173
|
699 data_buffer=self.signal,
|
amine@173
|
700 sr=16,
|
amine@173
|
701 sampling_rate=16,
|
amine@173
|
702 sample_width=2,
|
amine@173
|
703 channels=1,
|
amine@173
|
704 )
|
amine@172
|
705 self.assertRaises(DuplicateArgument, func)
|
amine@173
|
706
|
amine@172
|
707 def test_sample_width_alias(self):
|
amine@173
|
708 ads = ADSFactory.ads(
|
amine@218
|
709 data_buffer=self.signal,
|
amine@218
|
710 sampling_rate=16,
|
amine@218
|
711 sw=2,
|
amine@218
|
712 channels=1,
|
amine@218
|
713 block_dur=0.5,
|
amine@173
|
714 )
|
amine@173
|
715 swidth = ads.sample_width
|
amine@173
|
716 self.assertEqual(
|
amine@173
|
717 swidth,
|
amine@173
|
718 2,
|
amine@173
|
719 "Wrong sample width, expected: 2, found: {0}".format(swidth),
|
amine@173
|
720 )
|
amine@173
|
721
|
amine@172
|
722 def test_sample_width_duplicate(self):
|
amine@173
|
723 func = partial(
|
amine@173
|
724 ADSFactory.ads,
|
amine@173
|
725 data_buffer=self.signal,
|
amine@173
|
726 sampling_rate=16,
|
amine@173
|
727 sw=2,
|
amine@173
|
728 sample_width=2,
|
amine@173
|
729 channels=1,
|
amine@173
|
730 )
|
amine@172
|
731 self.assertRaises(DuplicateArgument, func)
|
amine@173
|
732
|
amine@172
|
733 def test_channels_alias(self):
|
amine@173
|
734 ads = ADSFactory.ads(
|
amine@218
|
735 data_buffer=self.signal,
|
amine@218
|
736 sampling_rate=16,
|
amine@218
|
737 sample_width=2,
|
amine@218
|
738 ch=1,
|
amine@218
|
739 block_dur=4,
|
amine@173
|
740 )
|
amine@173
|
741 channels = ads.channels
|
amine@173
|
742 self.assertEqual(
|
amine@173
|
743 channels,
|
amine@173
|
744 1,
|
amine@173
|
745 "Wrong number of channels, expected: 1, found: {0}".format(
|
amine@173
|
746 channels
|
amine@173
|
747 ),
|
amine@173
|
748 )
|
amine@173
|
749
|
amine@172
|
750 def test_channels_duplicate(self):
|
amine@173
|
751 func = partial(
|
amine@173
|
752 ADSFactory.ads,
|
amine@173
|
753 data_buffer=self.signal,
|
amine@173
|
754 sampling_rate=16,
|
amine@173
|
755 sample_width=2,
|
amine@173
|
756 ch=1,
|
amine@173
|
757 channels=1,
|
amine@173
|
758 )
|
amine@172
|
759 self.assertRaises(DuplicateArgument, func)
|
amine@173
|
760
|
amine@172
|
761 def test_block_size_alias(self):
|
amine@173
|
762 ads = ADSFactory.ads(
|
amine@173
|
763 data_buffer=self.signal,
|
amine@173
|
764 sampling_rate=16,
|
amine@173
|
765 sample_width=2,
|
amine@173
|
766 channels=1,
|
amine@173
|
767 bs=8,
|
amine@173
|
768 )
|
amine@173
|
769 size = ads.block_size
|
amine@173
|
770 self.assertEqual(
|
amine@173
|
771 size,
|
amine@173
|
772 8,
|
amine@173
|
773 "Wrong block_size using bs alias, expected: 8, found: {0}".format(
|
amine@173
|
774 size
|
amine@173
|
775 ),
|
amine@173
|
776 )
|
amine@173
|
777
|
amine@172
|
778 def test_block_size_duplicate(self):
|
amine@173
|
779 func = partial(
|
amine@173
|
780 ADSFactory.ads,
|
amine@173
|
781 data_buffer=self.signal,
|
amine@173
|
782 sampling_rate=16,
|
amine@173
|
783 sample_width=2,
|
amine@173
|
784 channels=1,
|
amine@173
|
785 bs=4,
|
amine@173
|
786 block_size=4,
|
amine@173
|
787 )
|
amine@172
|
788 self.assertRaises(DuplicateArgument, func)
|
amine@173
|
789
|
amine@172
|
790 def test_block_duration_alias(self):
|
amine@173
|
791 ads = ADSFactory.ads(
|
amine@173
|
792 data_buffer=self.signal,
|
amine@173
|
793 sampling_rate=16,
|
amine@173
|
794 sample_width=2,
|
amine@173
|
795 channels=1,
|
amine@173
|
796 bd=0.75,
|
amine@173
|
797 )
|
amine@172
|
798 # 0.75 ms = 0.75 * 16 = 12
|
amine@173
|
799 size = ads.block_size
|
amine@173
|
800 self.assertEqual(
|
amine@173
|
801 size,
|
amine@173
|
802 12,
|
amine@173
|
803 "Wrong block_size set with a block_dur alias 'bd', expected: 8, found: {0}".format(
|
amine@173
|
804 size
|
amine@173
|
805 ),
|
amine@173
|
806 )
|
amine@173
|
807
|
amine@172
|
808 def test_block_duration_duplicate(self):
|
amine@173
|
809 func = partial(
|
amine@173
|
810 ADSFactory.ads,
|
amine@173
|
811 data_buffer=self.signal,
|
amine@173
|
812 sampling_rate=16,
|
amine@173
|
813 sample_width=2,
|
amine@173
|
814 channels=1,
|
amine@173
|
815 bd=4,
|
amine@173
|
816 block_dur=4,
|
amine@173
|
817 )
|
amine@172
|
818 self.assertRaises(DuplicateArgument, func)
|
amine@173
|
819
|
amine@172
|
820 def test_block_size_duration_duplicate(self):
|
amine@173
|
821 func = partial(
|
amine@173
|
822 ADSFactory.ads,
|
amine@173
|
823 data_buffer=self.signal,
|
amine@173
|
824 sampling_rate=16,
|
amine@173
|
825 sample_width=2,
|
amine@173
|
826 channels=1,
|
amine@173
|
827 bd=4,
|
amine@173
|
828 bs=12,
|
amine@173
|
829 )
|
amine@172
|
830 self.assertRaises(DuplicateArgument, func)
|
amine@173
|
831
|
amine@172
|
832 def test_hop_duration_alias(self):
|
amine@173
|
833
|
amine@173
|
834 ads = ADSFactory.ads(
|
amine@173
|
835 data_buffer=self.signal,
|
amine@173
|
836 sampling_rate=16,
|
amine@173
|
837 sample_width=2,
|
amine@173
|
838 channels=1,
|
amine@173
|
839 bd=0.75,
|
amine@173
|
840 hd=0.5,
|
amine@173
|
841 )
|
amine@172
|
842 size = ads.hop_size
|
amine@173
|
843 self.assertEqual(
|
amine@173
|
844 size,
|
amine@173
|
845 8,
|
amine@173
|
846 "Wrong block_size using bs alias, expected: 8, found: {0}".format(
|
amine@173
|
847 size
|
amine@173
|
848 ),
|
amine@173
|
849 )
|
amine@173
|
850
|
amine@172
|
851 def test_hop_duration_duplicate(self):
|
amine@173
|
852
|
amine@173
|
853 func = partial(
|
amine@173
|
854 ADSFactory.ads,
|
amine@173
|
855 data_buffer=self.signal,
|
amine@173
|
856 sampling_rate=16,
|
amine@173
|
857 sample_width=2,
|
amine@173
|
858 channels=1,
|
amine@173
|
859 bd=0.75,
|
amine@173
|
860 hd=0.5,
|
amine@173
|
861 hop_dur=0.5,
|
amine@173
|
862 )
|
amine@172
|
863 self.assertRaises(DuplicateArgument, func)
|
amine@173
|
864
|
amine@172
|
865 def test_hop_size_duration_duplicate(self):
|
amine@173
|
866 func = partial(
|
amine@173
|
867 ADSFactory.ads,
|
amine@173
|
868 data_buffer=self.signal,
|
amine@173
|
869 sampling_rate=16,
|
amine@173
|
870 sample_width=2,
|
amine@173
|
871 channels=1,
|
amine@173
|
872 bs=8,
|
amine@173
|
873 hs=4,
|
amine@173
|
874 hd=1,
|
amine@173
|
875 )
|
amine@172
|
876 self.assertRaises(DuplicateArgument, func)
|
amine@173
|
877
|
amine@172
|
878 def test_hop_size_greater_than_block_size(self):
|
amine@173
|
879 func = partial(
|
amine@173
|
880 ADSFactory.ads,
|
amine@173
|
881 data_buffer=self.signal,
|
amine@173
|
882 sampling_rate=16,
|
amine@173
|
883 sample_width=2,
|
amine@173
|
884 channels=1,
|
amine@173
|
885 bs=4,
|
amine@173
|
886 hs=8,
|
amine@173
|
887 )
|
amine@172
|
888 self.assertRaises(ValueError, func)
|
amine@173
|
889
|
amine@172
|
890 def test_filename_alias(self):
|
amine@172
|
891 ads = ADSFactory.ads(fn=dataset.one_to_six_arabic_16000_mono_bc_noise)
|
amine@173
|
892
|
amine@172
|
893 def test_filename_duplicate(self):
|
amine@173
|
894
|
amine@173
|
895 func = partial(
|
amine@173
|
896 ADSFactory.ads,
|
amine@173
|
897 fn=dataset.one_to_six_arabic_16000_mono_bc_noise,
|
amine@173
|
898 filename=dataset.one_to_six_arabic_16000_mono_bc_noise,
|
amine@173
|
899 )
|
amine@172
|
900 self.assertRaises(DuplicateArgument, func)
|
amine@173
|
901
|
amine@172
|
902 def test_data_buffer_duplicate(self):
|
amine@173
|
903 func = partial(
|
amine@173
|
904 ADSFactory.ads,
|
amine@173
|
905 data_buffer=self.signal,
|
amine@173
|
906 db=self.signal,
|
amine@173
|
907 sampling_rate=16,
|
amine@173
|
908 sample_width=2,
|
amine@173
|
909 channels=1,
|
amine@173
|
910 )
|
amine@172
|
911 self.assertRaises(DuplicateArgument, func)
|
amine@173
|
912
|
amine@172
|
913 def test_max_time_alias(self):
|
amine@173
|
914 ads = ADSFactory.ads(
|
amine@173
|
915 data_buffer=self.signal,
|
amine@173
|
916 sampling_rate=16,
|
amine@173
|
917 sample_width=2,
|
amine@173
|
918 channels=1,
|
amine@173
|
919 mt=10,
|
amine@218
|
920 block_dur=0.5,
|
amine@173
|
921 )
|
amine@173
|
922 self.assertEqual(
|
amine@173
|
923 ads.max_read,
|
amine@173
|
924 10,
|
amine@173
|
925 "Wrong AudioDataSource.max_read, expected: 10, found: {}".format(
|
amine@173
|
926 ads.max_read
|
amine@173
|
927 ),
|
amine@173
|
928 )
|
amine@173
|
929
|
amine@172
|
930 def test_max_time_duplicate(self):
|
amine@173
|
931 func = partial(
|
amine@173
|
932 ADSFactory.ads,
|
amine@173
|
933 data_buffer=self.signal,
|
amine@173
|
934 sampling_rate=16,
|
amine@173
|
935 sample_width=2,
|
amine@173
|
936 channels=1,
|
amine@173
|
937 mt=True,
|
amine@173
|
938 max_time=True,
|
amine@173
|
939 )
|
amine@173
|
940
|
amine@172
|
941 self.assertRaises(DuplicateArgument, func)
|
amine@173
|
942
|
amine@172
|
943 def test_record_alias(self):
|
amine@173
|
944 ads = ADSFactory.ads(
|
amine@173
|
945 data_buffer=self.signal,
|
amine@173
|
946 sampling_rate=16,
|
amine@173
|
947 sample_width=2,
|
amine@173
|
948 channels=1,
|
amine@173
|
949 rec=True,
|
amine@218
|
950 block_dur=0.5,
|
amine@173
|
951 )
|
amine@173
|
952 self.assertTrue(
|
amine@173
|
953 ads.rewindable, "AudioDataSource.rewindable expected to be True"
|
amine@173
|
954 )
|
amine@173
|
955
|
amine@172
|
956 def test_record_duplicate(self):
|
amine@173
|
957 func = partial(
|
amine@173
|
958 ADSFactory.ads,
|
amine@173
|
959 data_buffer=self.signal,
|
amine@173
|
960 sampling_rate=16,
|
amine@173
|
961 sample_width=2,
|
amine@173
|
962 channels=1,
|
amine@173
|
963 rec=True,
|
amine@173
|
964 record=True,
|
amine@173
|
965 )
|
amine@172
|
966 self.assertRaises(DuplicateArgument, func)
|
amine@173
|
967
|
amine@172
|
968 def test_Limiter_Recorder_Overlap_Deco_rewind_and_read_alias(self):
|
amine@173
|
969
|
amine@172
|
970 # Use arbitrary valid block_size and hop_size
|
amine@172
|
971 block_size = 5
|
amine@172
|
972 hop_size = 4
|
amine@173
|
973
|
amine@173
|
974 ads = ADSFactory.ads(
|
amine@173
|
975 db=self.signal,
|
amine@173
|
976 sr=16,
|
amine@173
|
977 sw=2,
|
amine@173
|
978 ch=1,
|
amine@173
|
979 mt=0.80,
|
amine@173
|
980 bs=block_size,
|
amine@173
|
981 hs=hop_size,
|
amine@173
|
982 rec=True,
|
amine@173
|
983 )
|
amine@173
|
984
|
amine@172
|
985 # Read all available data overlapping blocks
|
amine@172
|
986 ads.open()
|
amine@172
|
987 i = 0
|
amine@172
|
988 while True:
|
amine@172
|
989 block = ads.read()
|
amine@172
|
990 if block is None:
|
amine@172
|
991 break
|
amine@172
|
992 i += 1
|
amine@173
|
993
|
amine@172
|
994 ads.rewind()
|
amine@173
|
995
|
amine@172
|
996 # Build a BufferAudioSource
|
amine@173
|
997 audio_source = BufferAudioSource(
|
amine@173
|
998 self.signal, ads.sampling_rate, ads.sample_width, ads.channels
|
amine@173
|
999 )
|
amine@172
|
1000 audio_source.open()
|
amine@173
|
1001
|
amine@173
|
1002 # Compare all blocks read from AudioDataSource to those read
|
amine@173
|
1003 # from an audio source with manual position definition
|
amine@172
|
1004 for j in range(i):
|
amine@172
|
1005 tmp = audio_source.read(block_size)
|
amine@172
|
1006 block = ads.read()
|
amine@173
|
1007 self.assertEqual(
|
amine@173
|
1008 block,
|
amine@173
|
1009 tmp,
|
amine@173
|
1010 "Unexpected block (N={0}) read from OverlapADS".format(i),
|
amine@173
|
1011 )
|
amine@216
|
1012 audio_source.position = (j + 1) * hop_size
|
amine@172
|
1013 ads.close()
|
amine@172
|
1014 audio_source.close()
|
amine@173
|
1015
|
amine@172
|
1016
|
amine@172
|
1017 if __name__ == "__main__":
|
amine@172
|
1018 unittest.main()
|