annotate tests/test_AudioDataSource.py @ 314:12a030453422

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