annotate tests/test_core.py @ 318:bf4a8834c5ec

Refactor io
author Amine Sehili <amine.sehili@gmail.com>
date Fri, 18 Oct 2019 21:36:51 +0100
parents b6c5125be036
children 7c2fb10b949f
rev   line source
amine@192 1 import os
amine@221 2 import math
amine@88 3 from random import random
amine@192 4 from tempfile import TemporaryDirectory
amine@252 5 from array import array as array_
amine@221 6 from unittest import TestCase
amine@264 7 from mock import patch
amine@86 8 from genty import genty, genty_dataset
amine@207 9 from auditok import split, AudioRegion, AudioParameterError
amine@308 10 from auditok.core import _duration_to_nb_windows, _read_chunks_online
amine@212 11 from auditok.util import AudioDataSource
amine@315 12 from auditok.io import get_audio_source
amine@86 13
amine@86 14
amine@299 15 def _make_random_length_regions(
amine@299 16 byte_seq, sampling_rate, sample_width, channels
amine@299 17 ):
amine@88 18 regions = []
amine@88 19 for b in byte_seq:
amine@88 20 duration = round(random() * 10, 6)
amine@95 21 data = b * int(duration * sampling_rate) * sample_width * channels
amine@244 22 region = AudioRegion(data, sampling_rate, sample_width, channels)
amine@88 23 regions.append(region)
amine@88 24 return regions
amine@88 25
amine@88 26
amine@86 27 @genty
amine@215 28 class TestFunctions(TestCase):
amine@215 29 @genty_dataset(
amine@221 30 zero_duration=(0, 1, None, 0),
amine@221 31 multiple=(0.3, 0.1, round, 3),
amine@221 32 not_multiple_ceil=(0.35, 0.1, math.ceil, 4),
amine@221 33 not_multiple_floor=(0.35, 0.1, math.floor, 3),
amine@221 34 small_duration=(0.05, 0.1, round, 0),
amine@221 35 small_duration_ceil=(0.05, 0.1, math.ceil, 1),
amine@233 36 with_round_error=(0.3, 0.1, math.floor, 3, {"epsilon": 1e-6}),
amine@221 37 negative_duration=(-0.5, 0.1, math.ceil, ValueError),
amine@221 38 negative_analysis_window=(0.5, -0.1, math.ceil, ValueError),
amine@215 39 )
amine@221 40 def test_duration_to_nb_windows(
amine@232 41 self, duration, analysis_window, round_fn, expected, kwargs=None
amine@221 42 ):
amine@221 43 if expected == ValueError:
amine@215 44 with self.assertRaises(expected):
amine@221 45 _duration_to_nb_windows(duration, analysis_window, round_fn)
amine@215 46 else:
amine@232 47 if kwargs is None:
amine@232 48 kwargs = {}
amine@221 49 result = _duration_to_nb_windows(
amine@232 50 duration, analysis_window, round_fn, **kwargs
amine@221 51 )
amine@215 52 self.assertEqual(result, expected)
amine@215 53
amine@215 54
amine@215 55 @genty
amine@207 56 class TestSplit(TestCase):
amine@207 57 @genty_dataset(
amine@299 58 simple=(
amine@299 59 0.2,
amine@299 60 5,
amine@299 61 0.2,
amine@299 62 False,
amine@299 63 False,
amine@299 64 {"eth": 50},
amine@299 65 [(2, 16), (17, 31), (34, 76)],
amine@299 66 ),
amine@214 67 short_max_dur=(
amine@214 68 0.3,
amine@214 69 2,
amine@214 70 0.2,
amine@214 71 False,
amine@214 72 False,
amine@214 73 {"eth": 50},
amine@214 74 [(2, 16), (17, 31), (34, 54), (54, 74), (74, 76)],
amine@214 75 ),
amine@214 76 long_min_dur=(3, 5, 0.2, False, False, {"eth": 50}, [(34, 76)]),
amine@214 77 long_max_silence=(0.2, 80, 10, False, False, {"eth": 50}, [(2, 76)]),
amine@214 78 zero_max_silence=(
amine@214 79 0.2,
amine@214 80 5,
amine@214 81 0.0,
amine@214 82 False,
amine@214 83 False,
amine@214 84 {"eth": 50},
amine@214 85 [(2, 14), (17, 24), (26, 29), (34, 76)],
amine@214 86 ),
amine@207 87 low_energy_threshold=(
amine@207 88 0.2,
amine@207 89 5,
amine@207 90 0.2,
amine@207 91 False,
amine@207 92 False,
amine@207 93 {"energy_threshold": 40},
amine@207 94 [(0, 50), (50, 76)],
amine@207 95 ),
amine@299 96 high_energy_threshold=(
amine@299 97 0.2,
amine@299 98 5,
amine@299 99 0.2,
amine@299 100 False,
amine@299 101 False,
amine@299 102 {"energy_threshold": 60},
amine@299 103 [],
amine@299 104 ),
amine@207 105 trim_leading_and_trailing_silence=(
amine@207 106 0.2,
amine@207 107 10, # use long max_dur
amine@207 108 0.5, # and a max_silence longer than any inter-region silence
amine@207 109 True,
amine@207 110 False,
amine@207 111 {"eth": 50},
amine@207 112 [(2, 76)],
amine@207 113 ),
amine@207 114 drop_trailing_silence=(
amine@207 115 0.2,
amine@207 116 5,
amine@207 117 0.2,
amine@207 118 True,
amine@207 119 False,
amine@207 120 {"eth": 50},
amine@207 121 [(2, 14), (17, 29), (34, 76)],
amine@207 122 ),
amine@299 123 drop_trailing_silence_2=(
amine@299 124 1.5,
amine@299 125 5,
amine@299 126 0.2,
amine@299 127 True,
amine@299 128 False,
amine@299 129 {"eth": 50},
amine@299 130 [(34, 76)],
amine@299 131 ),
amine@207 132 strict_min_dur=(
amine@207 133 0.3,
amine@207 134 2,
amine@207 135 0.2,
amine@207 136 False,
amine@207 137 True,
amine@207 138 {"eth": 50},
amine@207 139 [(2, 16), (17, 31), (34, 54), (54, 74)],
amine@207 140 ),
amine@207 141 )
amine@207 142 def test_split_params(
amine@207 143 self,
amine@207 144 min_dur,
amine@207 145 max_dur,
amine@207 146 max_silence,
amine@207 147 drop_trailing_silence,
amine@207 148 strict_min_dur,
amine@207 149 kwargs,
amine@207 150 expected,
amine@207 151 ):
amine@207 152 with open("tests/data/test_split_10HZ_mono.raw", "rb") as fp:
amine@207 153 data = fp.read()
amine@207 154
amine@207 155 regions = split(
amine@207 156 data,
amine@207 157 min_dur,
amine@207 158 max_dur,
amine@207 159 max_silence,
amine@207 160 drop_trailing_silence,
amine@207 161 strict_min_dur,
amine@207 162 analysis_window=0.1,
amine@207 163 sr=10,
amine@207 164 sw=2,
amine@207 165 ch=1,
amine@207 166 **kwargs
amine@207 167 )
amine@255 168
amine@255 169 region = AudioRegion(data, 10, 2, 1)
amine@255 170 regions_ar = region.split(
amine@255 171 min_dur,
amine@255 172 max_dur,
amine@255 173 max_silence,
amine@255 174 drop_trailing_silence,
amine@255 175 strict_min_dur,
amine@255 176 analysis_window=0.1,
amine@255 177 **kwargs
amine@255 178 )
amine@255 179
amine@207 180 regions = list(regions)
amine@255 181 regions_ar = list(regions_ar)
amine@207 182 err_msg = "Wrong number of regions after split, expected: "
amine@210 183 err_msg += "{}, found: {}".format(len(expected), len(regions))
amine@207 184 self.assertEqual(len(regions), len(expected), err_msg)
amine@255 185 err_msg = "Wrong number of regions after AudioRegion.split, expected: "
amine@255 186 err_msg += "{}, found: {}".format(len(expected), len(regions_ar))
amine@255 187 self.assertEqual(len(regions_ar), len(expected), err_msg)
amine@207 188
amine@207 189 sample_width = 2
amine@255 190 for reg, reg_ar, exp in zip(regions, regions_ar, expected):
amine@207 191 onset, offset = exp
amine@207 192 exp_data = data[onset * sample_width : offset * sample_width]
amine@207 193 self.assertEqual(bytes(reg), exp_data)
amine@255 194 self.assertEqual(reg, reg_ar)
amine@299 195
amine@211 196 @genty_dataset(
amine@241 197 stereo_all_default=(2, {}, [(2, 32), (34, 76)]),
amine@213 198 mono_max_read=(1, {"max_read": 5}, [(2, 16), (17, 31), (34, 50)]),
amine@213 199 mono_max_read_short_name=(1, {"mr": 5}, [(2, 16), (17, 31), (34, 50)]),
amine@211 200 mono_use_channel_1=(
amine@211 201 1,
amine@241 202 {"eth": 50, "use_channel": 0},
amine@211 203 [(2, 16), (17, 31), (34, 76)],
amine@211 204 ),
amine@211 205 mono_uc_1=(1, {"eth": 50, "uc": 1}, [(2, 16), (17, 31), (34, 76)]),
amine@211 206 mono_use_channel_None=(
amine@211 207 1,
amine@211 208 {"eth": 50, "use_channel": None},
amine@211 209 [(2, 16), (17, 31), (34, 76)],
amine@211 210 ),
amine@211 211 stereo_use_channel_1=(
amine@211 212 2,
amine@241 213 {"eth": 50, "use_channel": 0},
amine@211 214 [(2, 16), (17, 31), (34, 76)],
amine@211 215 ),
amine@299 216 stereo_use_channel_no_use_channel_given=(
amine@299 217 2,
amine@299 218 {"eth": 50},
amine@299 219 [(2, 32), (34, 76)],
amine@299 220 ),
amine@211 221 stereo_use_channel_minus_2=(
amine@211 222 2,
amine@211 223 {"eth": 50, "use_channel": -2},
amine@211 224 [(2, 16), (17, 31), (34, 76)],
amine@211 225 ),
amine@241 226 stereo_uc_2=(2, {"eth": 50, "uc": 1}, [(10, 32), (36, 76)]),
amine@211 227 stereo_uc_minus_1=(2, {"eth": 50, "uc": -1}, [(10, 32), (36, 76)]),
amine@299 228 mono_uc_mix=(
amine@299 229 1,
amine@299 230 {"eth": 50, "uc": "mix"},
amine@299 231 [(2, 16), (17, 31), (34, 76)],
amine@299 232 ),
amine@213 233 stereo_use_channel_mix=(
amine@213 234 2,
amine@213 235 {"energy_threshold": 53.5, "use_channel": "mix"},
amine@213 236 [(54, 76)],
amine@213 237 ),
amine@213 238 stereo_uc_mix=(2, {"eth": 52, "uc": "mix"}, [(17, 26), (54, 76)]),
amine@299 239 stereo_uc_mix_default_eth=(
amine@299 240 2,
amine@299 241 {"uc": "mix"},
amine@299 242 [(10, 16), (17, 31), (36, 76)],
amine@299 243 ),
amine@211 244 )
amine@211 245 def test_split_kwargs(self, channels, kwargs, expected):
amine@211 246
amine@211 247 mono_or_stereo = "mono" if channels == 1 else "stereo"
amine@211 248 filename = "tests/data/test_split_10HZ_{}.raw".format(mono_or_stereo)
amine@211 249 with open(filename, "rb") as fp:
amine@211 250 data = fp.read()
amine@211 251
amine@211 252 regions = split(
amine@211 253 data,
amine@211 254 min_dur=0.2,
amine@211 255 max_dur=5,
amine@211 256 max_silence=0.2,
amine@211 257 drop_trailing_silence=False,
amine@211 258 strict_min_dur=False,
amine@211 259 analysis_window=0.1,
amine@211 260 sr=10,
amine@211 261 sw=2,
amine@211 262 ch=channels,
amine@211 263 **kwargs
amine@211 264 )
amine@255 265
amine@255 266 region = AudioRegion(data, 10, 2, channels)
amine@306 267 max_read = kwargs.get("max_read", kwargs.get("mr"))
amine@306 268 if max_read is not None:
amine@306 269 region = region.sec[:max_read]
amine@306 270 kwargs.pop("max_read", None)
amine@306 271 kwargs.pop("mr", None)
amine@306 272
amine@255 273 regions_ar = region.split(
amine@255 274 min_dur=0.2,
amine@255 275 max_dur=5,
amine@255 276 max_silence=0.2,
amine@255 277 drop_trailing_silence=False,
amine@255 278 strict_min_dur=False,
amine@255 279 analysis_window=0.1,
amine@255 280 **kwargs
amine@255 281 )
amine@255 282
amine@212 283 regions = list(regions)
amine@255 284 regions_ar = list(regions_ar)
amine@211 285 err_msg = "Wrong number of regions after split, expected: "
amine@241 286 err_msg += "{}, found: {}".format(len(expected), len(regions))
amine@211 287 self.assertEqual(len(regions), len(expected), err_msg)
amine@255 288 err_msg = "Wrong number of regions after AudioRegion.split, expected: "
amine@255 289 err_msg += "{}, found: {}".format(len(expected), len(regions_ar))
amine@255 290 self.assertEqual(len(regions_ar), len(expected), err_msg)
amine@255 291
amine@255 292 sample_width = 2
amine@241 293 sample_size_bytes = sample_width * channels
amine@255 294 for reg, reg_ar, exp in zip(regions, regions_ar, expected):
amine@212 295 onset, offset = exp
amine@299 296 exp_data = data[
amine@299 297 onset * sample_size_bytes : offset * sample_size_bytes
amine@299 298 ]
amine@241 299 self.assertEqual(len(bytes(reg)), len(exp_data))
amine@255 300 self.assertEqual(reg, reg_ar)
amine@211 301
amine@212 302 @genty_dataset(
amine@299 303 mono_aw_0_2_max_silence_0_2=(
amine@299 304 0.2,
amine@299 305 5,
amine@299 306 0.2,
amine@299 307 1,
amine@299 308 {"aw": 0.2},
amine@299 309 [(2, 30), (34, 76)],
amine@299 310 ),
amine@299 311 mono_aw_0_2_max_silence_0_3=(
amine@299 312 0.2,
amine@299 313 5,
amine@299 314 0.3,
amine@299 315 1,
amine@299 316 {"aw": 0.2},
amine@299 317 [(2, 30), (34, 76)],
amine@299 318 ),
amine@299 319 mono_aw_0_2_max_silence_0_4=(
amine@299 320 0.2,
amine@299 321 5,
amine@299 322 0.4,
amine@299 323 1,
amine@299 324 {"aw": 0.2},
amine@299 325 [(2, 32), (34, 76)],
amine@299 326 ),
amine@231 327 mono_aw_0_2_max_silence_0=(
amine@231 328 0.2,
amine@231 329 5,
amine@231 330 0,
amine@231 331 1,
amine@241 332 {"aw": 0.2},
amine@231 333 [(2, 14), (16, 24), (26, 28), (34, 76)],
amine@231 334 ),
amine@241 335 mono_aw_0_2=(0.2, 5, 0.2, 1, {"aw": 0.2}, [(2, 30), (34, 76)]),
amine@231 336 mono_aw_0_3_max_silence_0=(
amine@231 337 0.3,
amine@231 338 5,
amine@231 339 0,
amine@231 340 1,
amine@241 341 {"aw": 0.3},
amine@231 342 [(3, 12), (15, 24), (36, 76)],
amine@231 343 ),
amine@299 344 mono_aw_0_3_max_silence_0_3=(
amine@299 345 0.3,
amine@299 346 5,
amine@299 347 0.3,
amine@299 348 1,
amine@299 349 {"aw": 0.3},
amine@299 350 [(3, 27), (36, 76)],
amine@299 351 ),
amine@299 352 mono_aw_0_3_max_silence_0_5=(
amine@299 353 0.3,
amine@299 354 5,
amine@299 355 0.5,
amine@299 356 1,
amine@299 357 {"aw": 0.3},
amine@299 358 [(3, 27), (36, 76)],
amine@299 359 ),
amine@299 360 mono_aw_0_3_max_silence_0_6=(
amine@299 361 0.3,
amine@299 362 5,
amine@299 363 0.6,
amine@299 364 1,
amine@299 365 {"aw": 0.3},
amine@299 366 [(3, 30), (36, 76)],
amine@299 367 ),
amine@231 368 mono_aw_0_4_max_silence_0=(
amine@231 369 0.2,
amine@231 370 5,
amine@232 371 0,
amine@231 372 1,
amine@241 373 {"aw": 0.4},
amine@231 374 [(4, 12), (16, 24), (36, 76)],
amine@231 375 ),
amine@231 376 mono_aw_0_4_max_silence_0_3=(
amine@231 377 0.2,
amine@231 378 5,
amine@231 379 0.3,
amine@231 380 1,
amine@241 381 {"aw": 0.4},
amine@231 382 [(4, 12), (16, 24), (36, 76)],
amine@231 383 ),
amine@299 384 mono_aw_0_4_max_silence_0_4=(
amine@299 385 0.2,
amine@299 386 5,
amine@299 387 0.4,
amine@299 388 1,
amine@299 389 {"aw": 0.4},
amine@299 390 [(4, 28), (36, 76)],
amine@299 391 ),
amine@316 392 stereo_uc_None_analysis_window_0_2=(
amine@316 393 0.2,
amine@316 394 5,
amine@316 395 0.2,
amine@316 396 2,
amine@316 397 {"analysis_window": 0.2},
amine@316 398 [(2, 32), (34, 76)],
amine@316 399 ),
amine@316 400 stereo_uc_any_analysis_window_0_2=(
amine@316 401 0.2,
amine@316 402 5,
amine@316 403 0.2,
amine@316 404 2,
amine@316 405 {"uc": None, "analysis_window": 0.2},
amine@316 406 [(2, 32), (34, 76)],
amine@316 407 ),
amine@316 408 stereo_use_channel_None_aw_0_3_max_silence_0_2=(
amine@316 409 0.2,
amine@316 410 5,
amine@316 411 0.2,
amine@316 412 2,
amine@316 413 {"use_channel": None, "analysis_window": 0.3},
amine@316 414 [(3, 30), (36, 76)],
amine@316 415 ),
amine@316 416 stereo_use_channel_any_aw_0_3_max_silence_0_3=(
amine@316 417 0.2,
amine@316 418 5,
amine@316 419 0.3,
amine@316 420 2,
amine@316 421 {"use_channel": "any", "analysis_window": 0.3},
amine@316 422 [(3, 33), (36, 76)],
amine@316 423 ),
amine@316 424 stereo_use_channel_None_aw_0_4_max_silence_0_2=(
amine@316 425 0.2,
amine@316 426 5,
amine@316 427 0.2,
amine@316 428 2,
amine@316 429 {"use_channel": None, "analysis_window": 0.4},
amine@316 430 [(4, 28), (36, 76)],
amine@316 431 ),
amine@316 432 stereo_use_channel_any_aw_0_3_max_silence_0_4=(
amine@316 433 0.2,
amine@316 434 5,
amine@316 435 0.4,
amine@316 436 2,
amine@316 437 {"use_channel": "any", "analysis_window": 0.4},
amine@316 438 [(4, 32), (36, 76)],
amine@316 439 ),
amine@241 440 stereo_uc_0_analysis_window_0_2=(
amine@241 441 0.2,
amine@241 442 5,
amine@241 443 0.2,
amine@241 444 2,
amine@241 445 {"uc": 0, "analysis_window": 0.2},
amine@241 446 [(2, 30), (34, 76)],
amine@241 447 ),
amine@220 448 stereo_uc_1_analysis_window_0_2=(
amine@220 449 0.2,
amine@220 450 5,
amine@220 451 0.2,
amine@220 452 2,
amine@220 453 {"uc": 1, "analysis_window": 0.2},
amine@231 454 [(10, 32), (36, 76)],
amine@231 455 ),
amine@233 456 stereo_uc_mix_aw_0_1_max_silence_0=(
amine@233 457 0.2,
amine@233 458 5,
amine@233 459 0,
amine@233 460 2,
amine@233 461 {"uc": "mix", "analysis_window": 0.1},
amine@233 462 [(10, 14), (17, 24), (26, 29), (36, 76)],
amine@233 463 ),
amine@233 464 stereo_uc_mix_aw_0_1_max_silence_0_1=(
amine@233 465 0.2,
amine@233 466 5,
amine@233 467 0.1,
amine@233 468 2,
amine@233 469 {"uc": "mix", "analysis_window": 0.1},
amine@233 470 [(10, 15), (17, 25), (26, 30), (36, 76)],
amine@233 471 ),
amine@233 472 stereo_uc_mix_aw_0_1_max_silence_0_2=(
amine@233 473 0.2,
amine@233 474 5,
amine@233 475 0.2,
amine@233 476 2,
amine@233 477 {"uc": "mix", "analysis_window": 0.1},
amine@233 478 [(10, 16), (17, 31), (36, 76)],
amine@233 479 ),
amine@233 480 stereo_uc_mix_aw_0_1_max_silence_0_3=(
amine@233 481 0.2,
amine@233 482 5,
amine@233 483 0.3,
amine@233 484 2,
amine@233 485 {"uc": "mix", "analysis_window": 0.1},
amine@233 486 [(10, 32), (36, 76)],
amine@233 487 ),
amine@316 488 stereo_uc_avg_aw_0_2_max_silence_0_min_dur_0_3=(
amine@233 489 0.3,
amine@233 490 5,
amine@233 491 0,
amine@233 492 2,
amine@316 493 {"uc": "avg", "analysis_window": 0.2},
amine@233 494 [(10, 14), (16, 24), (36, 76)],
amine@233 495 ),
amine@316 496 stereo_uc_average_aw_0_2_max_silence_0_min_dur_0_41=(
amine@233 497 0.41,
amine@233 498 5,
amine@233 499 0,
amine@233 500 2,
amine@316 501 {"uc": "average", "analysis_window": 0.2},
amine@233 502 [(16, 24), (36, 76)],
amine@233 503 ),
amine@233 504 stereo_uc_mix_aw_0_2_max_silence_0_1=(
amine@233 505 0.2,
amine@233 506 5,
amine@233 507 0.1,
amine@233 508 2,
amine@233 509 {"uc": "mix", "analysis_window": 0.2},
amine@233 510 [(10, 14), (16, 24), (26, 28), (36, 76)],
amine@233 511 ),
amine@233 512 stereo_uc_mix_aw_0_2_max_silence_0_2=(
amine@233 513 0.2,
amine@233 514 5,
amine@233 515 0.2,
amine@233 516 2,
amine@233 517 {"uc": "mix", "analysis_window": 0.2},
amine@233 518 [(10, 30), (36, 76)],
amine@233 519 ),
amine@233 520 stereo_uc_mix_aw_0_2_max_silence_0_4=(
amine@233 521 0.2,
amine@233 522 5,
amine@233 523 0.4,
amine@233 524 2,
amine@233 525 {"uc": "mix", "analysis_window": 0.2},
amine@233 526 [(10, 32), (36, 76)],
amine@233 527 ),
amine@233 528 stereo_uc_mix_aw_0_2_max_silence_0_5=(
amine@233 529 0.2,
amine@233 530 5,
amine@233 531 0.5,
amine@233 532 2,
amine@233 533 {"uc": "mix", "analysis_window": 0.2},
amine@233 534 [(10, 32), (36, 76)],
amine@233 535 ),
amine@233 536 stereo_uc_mix_aw_0_2_max_silence_0_6=(
amine@233 537 0.2,
amine@233 538 5,
amine@233 539 0.6,
amine@233 540 2,
amine@233 541 {"uc": "mix", "analysis_window": 0.2},
amine@233 542 [(10, 34), (36, 76)],
amine@233 543 ),
amine@233 544 stereo_uc_mix_aw_0_3_max_silence_0=(
amine@233 545 0.2,
amine@233 546 5,
amine@233 547 0,
amine@233 548 2,
amine@233 549 {"uc": "mix", "analysis_window": 0.3},
amine@233 550 [(9, 24), (27, 30), (36, 76)],
amine@233 551 ),
amine@233 552 stereo_uc_mix_aw_0_3_max_silence_0_min_dur_0_3=(
amine@233 553 0.4,
amine@233 554 5,
amine@233 555 0,
amine@233 556 2,
amine@233 557 {"uc": "mix", "analysis_window": 0.3},
amine@233 558 [(9, 24), (36, 76)],
amine@233 559 ),
amine@233 560 stereo_uc_mix_aw_0_3_max_silence_0_6=(
amine@233 561 0.2,
amine@233 562 5,
amine@233 563 0.6,
amine@233 564 2,
amine@233 565 {"uc": "mix", "analysis_window": 0.3},
amine@233 566 [(9, 57), (57, 76)],
amine@233 567 ),
amine@233 568 stereo_uc_mix_aw_0_3_max_silence_0_6_max_dur_5_1=(
amine@233 569 0.2,
amine@233 570 5.1,
amine@233 571 0.6,
amine@233 572 2,
amine@233 573 {"uc": "mix", "analysis_window": 0.3},
amine@233 574 [(9, 60), (60, 76)],
amine@233 575 ),
amine@233 576 stereo_uc_mix_aw_0_3_max_silence_0_6_max_dur_5_2=(
amine@233 577 0.2,
amine@233 578 5.2,
amine@233 579 0.6,
amine@233 580 2,
amine@233 581 {"uc": "mix", "analysis_window": 0.3},
amine@233 582 [(9, 60), (60, 76)],
amine@233 583 ),
amine@233 584 stereo_uc_mix_aw_0_3_max_silence_0_6_max_dur_5_3=(
amine@233 585 0.2,
amine@233 586 5.3,
amine@233 587 0.6,
amine@233 588 2,
amine@233 589 {"uc": "mix", "analysis_window": 0.3},
amine@233 590 [(9, 60), (60, 76)],
amine@233 591 ),
amine@233 592 stereo_uc_mix_aw_0_3_max_silence_0_6_max_dur_5_4=(
amine@233 593 0.2,
amine@233 594 5.4,
amine@233 595 0.6,
amine@233 596 2,
amine@233 597 {"uc": "mix", "analysis_window": 0.3},
amine@233 598 [(9, 63), (63, 76)],
amine@233 599 ),
amine@233 600 stereo_uc_mix_aw_0_4_max_silence_0=(
amine@233 601 0.2,
amine@233 602 5,
amine@233 603 0,
amine@233 604 2,
amine@233 605 {"uc": "mix", "analysis_window": 0.4},
amine@233 606 [(16, 24), (36, 76)],
amine@233 607 ),
amine@233 608 stereo_uc_mix_aw_0_4_max_silence_0_3=(
amine@233 609 0.2,
amine@233 610 5,
amine@233 611 0.3,
amine@233 612 2,
amine@233 613 {"uc": "mix", "analysis_window": 0.4},
amine@233 614 [(16, 24), (36, 76)],
amine@233 615 ),
amine@233 616 stereo_uc_mix_aw_0_4_max_silence_0_4=(
amine@233 617 0.2,
amine@233 618 5,
amine@233 619 0.4,
amine@233 620 2,
amine@233 621 {"uc": "mix", "analysis_window": 0.4},
amine@233 622 [(16, 28), (36, 76)],
amine@233 623 ),
amine@220 624 )
amine@220 625 def test_split_analysis_window(
amine@220 626 self, min_dur, max_dur, max_silence, channels, kwargs, expected
amine@220 627 ):
amine@220 628
amine@220 629 mono_or_stereo = "mono" if channels == 1 else "stereo"
amine@220 630 filename = "tests/data/test_split_10HZ_{}.raw".format(mono_or_stereo)
amine@220 631 with open(filename, "rb") as fp:
amine@220 632 data = fp.read()
amine@220 633
amine@220 634 regions = split(
amine@220 635 data,
amine@220 636 min_dur=min_dur,
amine@220 637 max_dur=max_dur,
amine@220 638 max_silence=max_silence,
amine@220 639 drop_trailing_silence=False,
amine@220 640 strict_min_dur=False,
amine@220 641 sr=10,
amine@220 642 sw=2,
amine@220 643 ch=channels,
amine@316 644 eth=49.99,
amine@220 645 **kwargs
amine@220 646 )
amine@255 647
amine@255 648 region = AudioRegion(data, 10, 2, channels)
amine@255 649 regions_ar = region.split(
amine@255 650 min_dur=min_dur,
amine@255 651 max_dur=max_dur,
amine@255 652 max_silence=max_silence,
amine@255 653 drop_trailing_silence=False,
amine@255 654 strict_min_dur=False,
amine@316 655 eth=49.99,
amine@255 656 **kwargs
amine@255 657 )
amine@255 658
amine@220 659 regions = list(regions)
amine@255 660 regions_ar = list(regions_ar)
amine@255 661 err_msg = "Wrong number of regions after split, expected: "
amine@255 662 err_msg += "{}, found: {}".format(len(expected), len(regions))
amine@255 663 self.assertEqual(len(regions), len(expected), err_msg)
amine@255 664 err_msg = "Wrong number of regions after AudioRegion.split, expected: "
amine@255 665 err_msg += "{}, found: {}".format(len(expected), len(regions_ar))
amine@255 666 self.assertEqual(len(regions_ar), len(expected), err_msg)
amine@255 667
amine@220 668 sample_width = 2
amine@255 669 sample_size_bytes = sample_width * channels
amine@255 670 for reg, reg_ar, exp in zip(regions, regions_ar, expected):
amine@220 671 onset, offset = exp
amine@299 672 exp_data = data[
amine@299 673 onset * sample_size_bytes : offset * sample_size_bytes
amine@299 674 ]
amine@299 675 self.assertEqual(bytes(reg), exp_data)
amine@299 676 self.assertEqual(reg, reg_ar)
amine@299 677
amine@299 678 def test_split_custom_validator(self):
amine@299 679 filename = "tests/data/test_split_10HZ_mono.raw"
amine@299 680 with open(filename, "rb") as fp:
amine@299 681 data = fp.read()
amine@299 682
amine@299 683 regions = split(
amine@299 684 data,
amine@299 685 min_dur=0.2,
amine@299 686 max_dur=5,
amine@299 687 max_silence=0.2,
amine@299 688 drop_trailing_silence=False,
amine@299 689 strict_min_dur=False,
amine@299 690 sr=10,
amine@299 691 sw=2,
amine@299 692 ch=1,
amine@299 693 analysis_window=0.1,
amine@299 694 validator=lambda x: array_("h", x)[0] >= 320,
amine@299 695 )
amine@299 696
amine@299 697 region = AudioRegion(data, 10, 2, 1)
amine@299 698 regions_ar = region.split(
amine@299 699 min_dur=0.2,
amine@299 700 max_dur=5,
amine@299 701 max_silence=0.2,
amine@299 702 drop_trailing_silence=False,
amine@299 703 strict_min_dur=False,
amine@299 704 analysis_window=0.1,
amine@299 705 validator=lambda x: array_("h", x)[0] >= 320,
amine@299 706 )
amine@299 707
amine@299 708 expected = [(2, 16), (17, 31), (34, 76)]
amine@299 709 regions = list(regions)
amine@299 710 regions_ar = list(regions_ar)
amine@299 711 err_msg = "Wrong number of regions after split, expected: "
amine@299 712 err_msg += "{}, found: {}".format(len(expected), len(regions))
amine@299 713 self.assertEqual(len(regions), len(expected), err_msg)
amine@299 714 err_msg = "Wrong number of regions after AudioRegion.split, expected: "
amine@299 715 err_msg += "{}, found: {}".format(len(expected), len(regions_ar))
amine@299 716 self.assertEqual(len(regions_ar), len(expected), err_msg)
amine@299 717
amine@299 718 sample_size_bytes = 2
amine@299 719 for reg, reg_ar, exp in zip(regions, regions_ar, expected):
amine@299 720 onset, offset = exp
amine@299 721 exp_data = data[
amine@299 722 onset * sample_size_bytes : offset * sample_size_bytes
amine@299 723 ]
amine@220 724 self.assertEqual(bytes(reg), exp_data)
amine@255 725 self.assertEqual(reg, reg_ar)
amine@220 726
amine@220 727 @genty_dataset(
amine@212 728 filename_audio_format=(
amine@212 729 "tests/data/test_split_10HZ_stereo.raw",
amine@212 730 {"audio_format": "raw", "sr": 10, "sw": 2, "ch": 2},
amine@212 731 ),
amine@212 732 filename_audio_format_short_name=(
amine@212 733 "tests/data/test_split_10HZ_stereo.raw",
amine@212 734 {"fmt": "raw", "sr": 10, "sw": 2, "ch": 2},
amine@212 735 ),
amine@212 736 filename_no_audio_format=(
amine@212 737 "tests/data/test_split_10HZ_stereo.raw",
amine@212 738 {"sr": 10, "sw": 2, "ch": 2},
amine@212 739 ),
amine@212 740 filename_no_long_audio_params=(
amine@212 741 "tests/data/test_split_10HZ_stereo.raw",
amine@212 742 {"sampling_rate": 10, "sample_width": 2, "channels": 2},
amine@212 743 ),
amine@212 744 bytes_=(
amine@212 745 open("tests/data/test_split_10HZ_stereo.raw", "rb").read(),
amine@212 746 {"sr": 10, "sw": 2, "ch": 2},
amine@212 747 ),
amine@212 748 audio_reader=(
amine@212 749 AudioDataSource(
amine@212 750 "tests/data/test_split_10HZ_stereo.raw",
amine@212 751 sr=10,
amine@212 752 sw=2,
amine@212 753 ch=2,
amine@212 754 block_dur=0.1,
amine@212 755 ),
amine@212 756 {},
amine@212 757 ),
amine@212 758 audio_region=(
amine@212 759 AudioRegion(
amine@299 760 open("tests/data/test_split_10HZ_stereo.raw", "rb").read(),
amine@299 761 10,
amine@299 762 2,
amine@299 763 2,
amine@212 764 ),
amine@212 765 {},
amine@212 766 ),
amine@212 767 audio_source=(
amine@212 768 get_audio_source(
amine@212 769 "tests/data/test_split_10HZ_stereo.raw", sr=10, sw=2, ch=2
amine@212 770 ),
amine@212 771 {},
amine@212 772 ),
amine@212 773 )
amine@212 774 def test_split_input_type(self, input, kwargs):
amine@212 775
amine@241 776 with open("tests/data/test_split_10HZ_stereo.raw", "rb") as fp:
amine@212 777 data = fp.read()
amine@212 778
amine@212 779 regions = split(
amine@212 780 input,
amine@212 781 min_dur=0.2,
amine@212 782 max_dur=5,
amine@212 783 max_silence=0.2,
amine@212 784 drop_trailing_silence=False,
amine@212 785 strict_min_dur=False,
amine@212 786 analysis_window=0.1,
amine@212 787 **kwargs
amine@212 788 )
amine@212 789 regions = list(regions)
amine@241 790 expected = [(2, 32), (34, 76)]
amine@212 791 sample_width = 2
amine@212 792 err_msg = "Wrong number of regions after split, expected: "
amine@212 793 err_msg += "{}, found: {}".format(expected, regions)
amine@212 794 self.assertEqual(len(regions), len(expected), err_msg)
amine@211 795 for reg, exp in zip(regions, expected):
amine@211 796 onset, offset = exp
amine@299 797 exp_data = data[
amine@299 798 onset * sample_width * 2 : offset * sample_width * 2
amine@299 799 ]
amine@211 800 self.assertEqual(bytes(reg), exp_data)
amine@211 801
amine@223 802 @genty_dataset(
amine@223 803 min_dur_greater_than_max_dur=(0.5, 0.4, 0.1),
amine@223 804 durations_OK_but_wrong_number_of_analysis_windows=(0.44, 0.49, 0.1),
amine@223 805 )
amine@223 806 def test_split_wrong_min_max_dur(self, min_dur, max_dur, analysis_window):
amine@223 807
amine@223 808 with self.assertRaises(ValueError) as val_err:
amine@223 809 split(
amine@223 810 b"0" * 16,
amine@223 811 min_dur=min_dur,
amine@223 812 max_dur=max_dur,
amine@223 813 max_silence=0.2,
amine@223 814 sr=16000,
amine@223 815 sw=1,
amine@223 816 ch=1,
amine@223 817 analysis_window=analysis_window,
amine@223 818 )
amine@223 819
amine@223 820 err_msg = "'min_dur' ({0} sec.) results in {1} analysis "
amine@223 821 err_msg += "window(s) ({1} == ceil({0} / {2})) which is "
amine@223 822 err_msg += "higher than the number of analysis window(s) for "
amine@223 823 err_msg += "'max_dur' ({3} == floor({4} / {2}))"
amine@223 824
amine@223 825 err_msg = err_msg.format(
amine@223 826 min_dur,
amine@223 827 math.ceil(min_dur / analysis_window),
amine@223 828 analysis_window,
amine@223 829 math.floor(max_dur / analysis_window),
amine@223 830 max_dur,
amine@223 831 )
amine@223 832 self.assertEqual(err_msg, str(val_err.exception))
amine@223 833
amine@224 834 @genty_dataset(
amine@224 835 max_silence_equals_max_dur=(0.5, 0.5, 0.1),
amine@224 836 max_silence_greater_than_max_dur=(0.5, 0.4, 0.1),
amine@224 837 durations_OK_but_wrong_number_of_analysis_windows=(0.44, 0.49, 0.1),
amine@224 838 )
amine@224 839 def test_split_wrong_max_silence_max_dur(
amine@224 840 self, max_silence, max_dur, analysis_window
amine@224 841 ):
amine@224 842
amine@224 843 with self.assertRaises(ValueError) as val_err:
amine@224 844 split(
amine@224 845 b"0" * 16,
amine@224 846 min_dur=0.2,
amine@224 847 max_dur=max_dur,
amine@224 848 max_silence=max_silence,
amine@224 849 sr=16000,
amine@224 850 sw=1,
amine@224 851 ch=1,
amine@224 852 analysis_window=analysis_window,
amine@224 853 )
amine@224 854
amine@224 855 err_msg = "'max_silence' ({0} sec.) results in {1} analysis "
amine@224 856 err_msg += "window(s) ({1} == floor({0} / {2})) which is "
amine@224 857 err_msg += "higher or equal to the number of analysis window(s) for "
amine@224 858 err_msg += "'max_dur' ({3} == floor({4} / {2}))"
amine@224 859
amine@224 860 err_msg = err_msg.format(
amine@224 861 max_silence,
amine@224 862 math.floor(max_silence / analysis_window),
amine@224 863 analysis_window,
amine@224 864 math.floor(max_dur / analysis_window),
amine@224 865 max_dur,
amine@224 866 )
amine@224 867 self.assertEqual(err_msg, str(val_err.exception))
amine@224 868
amine@226 869 @genty_dataset(
amine@226 870 negative_min_dur=({"min_dur": -1},),
amine@226 871 zero_min_dur=({"min_dur": 0},),
amine@226 872 negative_max_dur=({"max_dur": -1},),
amine@226 873 zero_max_dur=({"max_dur": 0},),
amine@226 874 negative_max_silence=({"max_silence": -1},),
amine@237 875 zero_analysis_window=({"analysis_window": 0},),
amine@237 876 negative_analysis_window=({"analysis_window": -1},),
amine@226 877 )
amine@226 878 def test_split_negative_temporal_params(self, wrong_param):
amine@226 879
amine@237 880 params = {
amine@237 881 "min_dur": 0.2,
amine@237 882 "max_dur": 0.5,
amine@237 883 "max_silence": 0.1,
amine@237 884 "analysis_window": 0.1,
amine@237 885 }
amine@226 886 params.update(wrong_param)
amine@226 887 with self.assertRaises(ValueError) as val_err:
amine@226 888 split(None, **params)
amine@226 889
amine@226 890 name = set(wrong_param).pop()
amine@226 891 value = wrong_param[name]
amine@226 892 err_msg = "'{}' ({}) must be >{} 0".format(
amine@226 893 name, value, "=" if name == "max_silence" else ""
amine@226 894 )
amine@226 895 self.assertEqual(err_msg, str(val_err.exception))
amine@226 896
amine@236 897 def test_split_too_small_analysis_window(self):
amine@236 898 with self.assertRaises(ValueError) as val_err:
amine@236 899 split(b"", sr=10, sw=1, ch=1, analysis_window=0.09)
amine@236 900 err_msg = "Too small 'analysis_windows' (0.09) for sampling rate (10)."
amine@236 901 err_msg += " Analysis windows should at least be 1/10 to cover one "
amine@236 902 err_msg += "single data sample"
amine@236 903 self.assertEqual(err_msg, str(val_err.exception))
amine@299 904
amine@264 905 def test_split_and_plot(self):
amine@236 906
amine@264 907 with open("tests/data/test_split_10HZ_mono.raw", "rb") as fp:
amine@264 908 data = fp.read()
amine@264 909
amine@264 910 region = AudioRegion(data, 10, 2, 1)
amine@302 911 with patch("auditok.plotting.plot") as patch_fn:
amine@264 912 regions = region.split_and_plot(
amine@264 913 min_dur=0.2,
amine@264 914 max_dur=5,
amine@264 915 max_silence=0.2,
amine@264 916 drop_trailing_silence=False,
amine@264 917 strict_min_dur=False,
amine@264 918 analysis_window=0.1,
amine@264 919 sr=10,
amine@264 920 sw=2,
amine@264 921 ch=1,
amine@264 922 eth=50,
amine@264 923 )
amine@264 924 self.assertTrue(patch_fn.called)
amine@264 925 expected = [(2, 16), (17, 31), (34, 76)]
amine@264 926 sample_width = 2
amine@264 927 expected_regions = []
amine@264 928 for (onset, offset) in expected:
amine@264 929 onset *= sample_width
amine@264 930 offset *= sample_width
amine@264 931 expected_regions.append(AudioRegion(data[onset:offset], 10, 2, 1))
amine@264 932 self.assertEqual(regions, expected_regions)
amine@207 933
amine@306 934 def test_split_exception(self):
amine@306 935 with open("tests/data/test_split_10HZ_mono.raw", "rb") as fp:
amine@306 936 data = fp.read()
amine@306 937 region = AudioRegion(data, 10, 2, 1)
amine@306 938
amine@306 939 with self.assertRaises(RuntimeWarning):
amine@306 940 # max_read is not accepted when calling AudioRegion.split
amine@306 941 region.split(max_read=2)
amine@306 942
amine@299 943
amine@207 944 @genty
amine@207 945 class TestAudioRegion(TestCase):
amine@86 946 @genty_dataset(
amine@86 947 simple=(b"\0" * 8000, 0, 8000, 1, 1, 1, 1, 1000),
amine@299 948 one_ms_less_than_1_sec=(
amine@299 949 b"\0" * 7992,
amine@299 950 0,
amine@299 951 8000,
amine@299 952 1,
amine@299 953 1,
amine@299 954 0.999,
amine@299 955 0.999,
amine@299 956 999,
amine@299 957 ),
amine@86 958 tree_quarter_ms_less_than_1_sec=(
amine@86 959 b"\0" * 7994,
amine@86 960 0,
amine@86 961 8000,
amine@86 962 1,
amine@86 963 1,
amine@86 964 0.99925,
amine@86 965 0.99925,
amine@86 966 999,
amine@86 967 ),
amine@299 968 half_ms_less_than_1_sec=(
amine@299 969 b"\0" * 7996,
amine@299 970 0,
amine@299 971 8000,
amine@299 972 1,
amine@299 973 1,
amine@299 974 0.9995,
amine@299 975 0.9995,
amine@299 976 1000,
amine@299 977 ),
amine@86 978 quarter_ms_less_than_1_sec=(
amine@86 979 b"\0" * 7998,
amine@86 980 0,
amine@86 981 8000,
amine@86 982 1,
amine@86 983 1,
amine@86 984 0.99975,
amine@86 985 0.99975,
amine@86 986 1000,
amine@86 987 ),
amine@86 988 simple_sample_width_2=(b"\0" * 8000 * 2, 0, 8000, 2, 1, 1, 1, 1000),
amine@86 989 simple_stereo=(b"\0" * 8000 * 2, 0, 8000, 1, 2, 1, 1, 1000),
amine@86 990 simple_multichannel=(b"\0" * 8000 * 5, 0, 8000, 1, 5, 1, 1, 1000),
amine@86 991 simple_sample_width_2_multichannel=(
amine@86 992 b"\0" * 8000 * 2 * 5,
amine@86 993 0,
amine@86 994 8000,
amine@86 995 2,
amine@86 996 5,
amine@86 997 1,
amine@86 998 1,
amine@86 999 1000,
amine@86 1000 ),
amine@86 1001 one_ms_less_than_1s_sw_2_multichannel=(
amine@86 1002 b"\0" * 7992 * 2 * 5,
amine@86 1003 0,
amine@86 1004 8000,
amine@86 1005 2,
amine@86 1006 5,
amine@86 1007 0.999,
amine@86 1008 0.999,
amine@86 1009 999,
amine@86 1010 ),
amine@86 1011 tree_qrt_ms_lt_1_s_sw_2_multichannel=(
amine@86 1012 b"\0" * 7994 * 2 * 5,
amine@86 1013 0,
amine@86 1014 8000,
amine@86 1015 2,
amine@86 1016 5,
amine@86 1017 0.99925,
amine@86 1018 0.99925,
amine@86 1019 999,
amine@86 1020 ),
amine@86 1021 half_ms_lt_1s_sw_2_multichannel=(
amine@86 1022 b"\0" * 7996 * 2 * 5,
amine@86 1023 0,
amine@86 1024 8000,
amine@86 1025 2,
amine@86 1026 5,
amine@86 1027 0.9995,
amine@86 1028 0.9995,
amine@86 1029 1000,
amine@86 1030 ),
amine@86 1031 quarter_ms_lt_1s_sw_2_multichannel=(
amine@86 1032 b"\0" * 7998 * 2 * 5,
amine@86 1033 0,
amine@86 1034 8000,
amine@86 1035 2,
amine@86 1036 5,
amine@86 1037 0.99975,
amine@86 1038 0.99975,
amine@86 1039 1000,
amine@86 1040 ),
amine@86 1041 arbitrary_length_1=(
amine@86 1042 b"\0" * int(8000 * 1.33),
amine@86 1043 2.7,
amine@86 1044 8000,
amine@86 1045 1,
amine@86 1046 1,
amine@86 1047 4.03,
amine@86 1048 1.33,
amine@86 1049 1330,
amine@86 1050 ),
amine@86 1051 arbitrary_length_2=(
amine@86 1052 b"\0" * int(8000 * 0.476),
amine@86 1053 11.568,
amine@86 1054 8000,
amine@86 1055 1,
amine@86 1056 1,
amine@86 1057 12.044,
amine@86 1058 0.476,
amine@86 1059 476,
amine@86 1060 ),
amine@86 1061 arbitrary_length_sw_2_multichannel=(
amine@86 1062 b"\0" * int(8000 * 1.711) * 2 * 3,
amine@86 1063 9.415,
amine@86 1064 8000,
amine@86 1065 2,
amine@86 1066 3,
amine@86 1067 11.126,
amine@86 1068 1.711,
amine@86 1069 1711,
amine@86 1070 ),
amine@86 1071 arbitrary_samplig_rate=(
amine@86 1072 b"\0" * int(3172 * 1.318),
amine@86 1073 17.236,
amine@86 1074 3172,
amine@86 1075 1,
amine@86 1076 1,
amine@86 1077 17.236 + int(3172 * 1.318) / 3172,
amine@86 1078 int(3172 * 1.318) / 3172,
amine@86 1079 1318,
amine@86 1080 ),
amine@86 1081 arbitrary_sr_sw_2_multichannel=(
amine@86 1082 b"\0" * int(11317 * 0.716) * 2 * 3,
amine@86 1083 18.811,
amine@86 1084 11317,
amine@86 1085 2,
amine@86 1086 3,
amine@86 1087 18.811 + int(11317 * 0.716) / 11317,
amine@86 1088 int(11317 * 0.716) / 11317,
amine@86 1089 716,
amine@86 1090 ),
amine@86 1091 )
amine@86 1092 def test_creation(
amine@86 1093 self,
amine@86 1094 data,
amine@86 1095 start,
amine@86 1096 sampling_rate,
amine@86 1097 sample_width,
amine@86 1098 channels,
amine@86 1099 expected_end,
amine@86 1100 expected_duration_s,
amine@86 1101 expected_duration_ms,
amine@86 1102 ):
amine@244 1103 meta = {"start": start, "end": expected_end}
amine@244 1104 region = AudioRegion(data, sampling_rate, sample_width, channels, meta)
amine@86 1105 self.assertEqual(region.sampling_rate, sampling_rate)
amine@86 1106 self.assertEqual(region.sr, sampling_rate)
amine@86 1107 self.assertEqual(region.sample_width, sample_width)
amine@86 1108 self.assertEqual(region.sw, sample_width)
amine@86 1109 self.assertEqual(region.channels, channels)
amine@86 1110 self.assertEqual(region.ch, channels)
amine@244 1111 self.assertEqual(region.meta.start, start)
amine@244 1112 self.assertEqual(region.meta.end, expected_end)
amine@86 1113 self.assertEqual(region.duration, expected_duration_s)
amine@245 1114 self.assertEqual(len(region.ms), expected_duration_ms)
amine@86 1115 self.assertEqual(bytes(region), data)
amine@88 1116
amine@97 1117 def test_creation_invalid_data_exception(self):
amine@97 1118 with self.assertRaises(AudioParameterError) as audio_param_err:
amine@97 1119 _ = AudioRegion(
amine@244 1120 data=b"ABCDEFGHI", sampling_rate=8, sample_width=2, channels=1
amine@97 1121 )
amine@97 1122 self.assertEqual(
amine@97 1123 "The length of audio data must be an integer "
amine@97 1124 "multiple of `sample_width * channels`",
amine@97 1125 str(audio_param_err.exception),
amine@97 1126 )
amine@97 1127
amine@308 1128 @genty_dataset(
amine@308 1129 no_skip_read_all=(0, -1),
amine@308 1130 no_skip_read_all_stereo=(0, -1, 2),
amine@308 1131 skip_2_read_all=(2, -1),
amine@308 1132 skip_2_read_all_None=(2, None),
amine@308 1133 skip_2_read_3=(2, 3),
amine@308 1134 skip_2_read_3_5_stereo=(2, 3.5, 2),
amine@308 1135 skip_2_4_read_3_5_stereo=(2.4, 3.5, 2),
amine@308 1136 )
amine@308 1137 def test_load(self, skip, max_read, channels=1):
amine@308 1138 sampling_rate = 10
amine@308 1139 sample_width = 2
amine@308 1140 filename = "tests/data/test_split_10HZ_{}.raw"
amine@308 1141 filename = filename.format("mono" if channels == 1 else "stereo")
amine@308 1142 region = AudioRegion.load(
amine@308 1143 filename,
amine@308 1144 skip=skip,
amine@308 1145 max_read=max_read,
amine@308 1146 sr=sampling_rate,
amine@308 1147 sw=sample_width,
amine@308 1148 ch=channels,
amine@308 1149 )
amine@308 1150 with open(filename, "rb") as fp:
amine@308 1151 fp.read(round(skip * sampling_rate * sample_width * channels))
amine@308 1152 if max_read is None or max_read < 0:
amine@308 1153 to_read = -1
amine@308 1154 else:
amine@308 1155 to_read = round(
amine@308 1156 max_read * sampling_rate * sample_width * channels
amine@308 1157 )
amine@308 1158 expected = fp.read(to_read)
amine@308 1159 self.assertEqual(bytes(region), expected)
amine@308 1160
amine@308 1161 def test_load_from_microphone(self):
amine@308 1162 with patch("auditok.io.PyAudioSource") as patch_pyaudio_source:
amine@308 1163 with patch("auditok.core.AudioReader.read") as patch_reader:
amine@308 1164 patch_reader.return_value = None
amine@308 1165 with patch(
amine@308 1166 "auditok.core.AudioRegion.__init__"
amine@308 1167 ) as patch_AudioRegion:
amine@308 1168 patch_AudioRegion.return_value = None
amine@308 1169 AudioRegion.load(
amine@308 1170 None, skip=0, max_read=5, sr=16000, sw=2, ch=1
amine@308 1171 )
amine@308 1172 self.assertTrue(patch_pyaudio_source.called)
amine@308 1173 self.assertTrue(patch_reader.called)
amine@308 1174 self.assertTrue(patch_AudioRegion.called)
amine@308 1175
amine@308 1176 @genty_dataset(none=(None,), negative=(-1,))
amine@308 1177 def test_load_from_microphone_without_max_read_exception(self, max_read):
amine@307 1178 with self.assertRaises(ValueError) as val_err:
amine@308 1179 AudioRegion.load(None, max_read=max_read, sr=16000, sw=2, ch=1)
amine@307 1180 self.assertEqual(
amine@307 1181 "'max_read' should not be None when reading from microphone",
amine@307 1182 str(val_err.exception),
amine@307 1183 )
amine@307 1184
amine@308 1185 def test_load_from_microphone_with_nonzero_skip_exception(self):
amine@308 1186 with self.assertRaises(ValueError) as val_err:
amine@308 1187 AudioRegion.load(None, skip=1, max_read=5, sr=16000, sw=2, ch=1)
amine@308 1188 self.assertEqual(
amine@308 1189 "'skip' should be 0 when reading from microphone",
amine@308 1190 str(val_err.exception),
amine@308 1191 )
amine@308 1192
amine@88 1193 @genty_dataset(
amine@192 1194 simple=("output.wav", 1.230, "output.wav"),
amine@244 1195 start=("output_{meta.start:g}.wav", 1.230, "output_1.23.wav"),
amine@244 1196 start_2=("output_{meta.start}.wav", 1.233712, "output_1.233712.wav"),
amine@244 1197 start_3=("output_{meta.start:.2f}.wav", 1.2300001, "output_1.23.wav"),
amine@244 1198 start_4=("output_{meta.start:.3f}.wav", 1.233712, "output_1.234.wav"),
amine@299 1199 start_5=(
amine@299 1200 "output_{meta.start:.8f}.wav",
amine@299 1201 1.233712,
amine@299 1202 "output_1.23371200.wav",
amine@299 1203 ),
amine@192 1204 start_end_duration=(
amine@244 1205 "output_{meta.start}_{meta.end}_{duration}.wav",
amine@192 1206 1.455,
amine@192 1207 "output_1.455_2.455_1.0.wav",
amine@192 1208 ),
amine@192 1209 start_end_duration_2=(
amine@244 1210 "output_{meta.start}_{meta.end}_{duration}.wav",
amine@192 1211 1.455321,
amine@192 1212 "output_1.455321_2.455321_1.0.wav",
amine@192 1213 ),
amine@192 1214 )
amine@192 1215 def test_save(self, format, start, expected):
amine@192 1216 with TemporaryDirectory() as tmpdir:
amine@244 1217 region = AudioRegion(b"0" * 160, 160, 1, 1)
amine@244 1218 meta = {"start": start, "end": start + region.duration}
amine@244 1219 region.meta = meta
amine@192 1220 format = os.path.join(tmpdir, format)
amine@192 1221 filename = region.save(format)[len(tmpdir) + 1 :]
amine@192 1222 self.assertEqual(filename, expected)
amine@192 1223
amine@193 1224 def test_save_file_exists_exception(self):
amine@193 1225 with TemporaryDirectory() as tmpdir:
amine@193 1226 filename = os.path.join(tmpdir, "output.wav")
amine@193 1227 open(filename, "w").close()
amine@244 1228 region = AudioRegion(b"0" * 160, 160, 1, 1)
amine@193 1229 with self.assertRaises(FileExistsError):
amine@193 1230 region.save(filename, exists_ok=False)
amine@193 1231
amine@192 1232 @genty_dataset(
amine@194 1233 first_half=(
amine@244 1234 AudioRegion(b"a" * 80 + b"b" * 80, 160, 1, 1),
amine@194 1235 slice(0, 500),
amine@244 1236 b"a" * 80,
amine@244 1237 ),
amine@244 1238 second_half=(
amine@244 1239 AudioRegion(b"a" * 80 + b"b" * 80, 160, 1, 1),
amine@244 1240 slice(500, None),
amine@244 1241 b"b" * 80,
amine@244 1242 ),
amine@244 1243 second_half_negative=(
amine@244 1244 AudioRegion(b"a" * 80 + b"b" * 80, 160, 1, 1),
amine@244 1245 slice(-500, None),
amine@244 1246 b"b" * 80,
amine@244 1247 ),
amine@244 1248 middle=(
amine@244 1249 AudioRegion(b"a" * 80 + b"b" * 80, 160, 1, 1),
amine@244 1250 slice(200, 750),
amine@244 1251 b"a" * 48 + b"b" * 40,
amine@244 1252 ),
amine@244 1253 middle_negative=(
amine@244 1254 AudioRegion(b"a" * 80 + b"b" * 80, 160, 1, 1),
amine@244 1255 slice(-800, -250),
amine@244 1256 b"a" * 48 + b"b" * 40,
amine@244 1257 ),
amine@244 1258 middle_sw2=(
amine@244 1259 AudioRegion(b"a" * 160 + b"b" * 160, 160, 2, 1),
amine@244 1260 slice(200, 750),
amine@244 1261 b"a" * 96 + b"b" * 80,
amine@244 1262 ),
amine@244 1263 middle_ch2=(
amine@244 1264 AudioRegion(b"a" * 160 + b"b" * 160, 160, 1, 2),
amine@244 1265 slice(200, 750),
amine@244 1266 b"a" * 96 + b"b" * 80,
amine@244 1267 ),
amine@244 1268 middle_sw2_ch2=(
amine@244 1269 AudioRegion(b"a" * 320 + b"b" * 320, 160, 2, 2),
amine@244 1270 slice(200, 750),
amine@244 1271 b"a" * 192 + b"b" * 160,
amine@244 1272 ),
amine@244 1273 but_first_sample=(
amine@244 1274 AudioRegion(b"a" * 4000 + b"b" * 4000, 8000, 1, 1),
amine@244 1275 slice(1, None),
amine@244 1276 b"a" * (4000 - 8) + b"b" * 4000,
amine@244 1277 ),
amine@244 1278 but_first_sample_negative=(
amine@244 1279 AudioRegion(b"a" * 4000 + b"b" * 4000, 8000, 1, 1),
amine@244 1280 slice(-999, None),
amine@244 1281 b"a" * (4000 - 8) + b"b" * 4000,
amine@244 1282 ),
amine@244 1283 but_last_sample=(
amine@244 1284 AudioRegion(b"a" * 4000 + b"b" * 4000, 8000, 1, 1),
amine@244 1285 slice(0, 999),
amine@244 1286 b"a" * 4000 + b"b" * (4000 - 8),
amine@244 1287 ),
amine@244 1288 but_last_sample_negative=(
amine@244 1289 AudioRegion(b"a" * 4000 + b"b" * 4000, 8000, 1, 1),
amine@244 1290 slice(0, -1),
amine@244 1291 b"a" * 4000 + b"b" * (4000 - 8),
amine@244 1292 ),
amine@244 1293 big_negative_start=(
amine@244 1294 AudioRegion(b"a" * 160, 160, 1, 1),
amine@244 1295 slice(-5000, None),
amine@244 1296 b"a" * 160,
amine@244 1297 ),
amine@299 1298 big_negative_stop=(
amine@299 1299 AudioRegion(b"a" * 160, 160, 1, 1),
amine@299 1300 slice(None, -1500),
amine@299 1301 b"",
amine@299 1302 ),
amine@299 1303 empty=(
amine@299 1304 AudioRegion(b"a" * 80 + b"b" * 80, 160, 1, 1),
amine@299 1305 slice(0, 0),
amine@299 1306 b"",
amine@299 1307 ),
amine@244 1308 empty_start_stop_reversed=(
amine@244 1309 AudioRegion(b"a" * 80 + b"b" * 80, 160, 1, 1),
amine@244 1310 slice(200, 100),
amine@244 1311 b"",
amine@244 1312 ),
amine@244 1313 empty_big_positive_start=(
amine@244 1314 AudioRegion(b"a" * 80 + b"b" * 80, 160, 1, 1),
amine@244 1315 slice(2000, 3000),
amine@244 1316 b"",
amine@244 1317 ),
amine@244 1318 empty_negative_reversed=(
amine@244 1319 AudioRegion(b"a" * 80 + b"b" * 80, 160, 1, 1),
amine@244 1320 slice(-100, -200),
amine@244 1321 b"",
amine@244 1322 ),
amine@244 1323 empty_big_negative_stop=(
amine@244 1324 AudioRegion(b"a" * 80 + b"b" * 80, 160, 1, 1),
amine@244 1325 slice(0, -2000),
amine@244 1326 b"",
amine@244 1327 ),
amine@244 1328 arbitrary_sampling_rate=(
amine@244 1329 AudioRegion(b"a" * 124 + b"b" * 376, 1234, 1, 1),
amine@244 1330 slice(100, 200),
amine@244 1331 b"a" + b"b" * 123,
amine@244 1332 ),
amine@244 1333 )
amine@244 1334 def test_region_temporal_slicing(self, region, slice_, expected_data):
amine@244 1335 sub_region = region.millis[slice_]
amine@244 1336 self.assertEqual(bytes(sub_region), expected_data)
amine@244 1337 start_sec = slice_.start / 1000 if slice_.start is not None else None
amine@244 1338 stop_sec = slice_.stop / 1000 if slice_.stop is not None else None
amine@244 1339 sub_region = region.sec[start_sec:stop_sec]
amine@244 1340 self.assertEqual(bytes(sub_region), expected_data)
amine@244 1341
amine@244 1342 @genty_dataset(
amine@244 1343 first_half=(
amine@244 1344 AudioRegion(b"a" * 80 + b"b" * 80, 160, 1, 1),
amine@244 1345 slice(0, 80),
amine@194 1346 0,
amine@194 1347 b"a" * 80,
amine@194 1348 ),
amine@194 1349 second_half=(
amine@244 1350 AudioRegion(b"a" * 80 + b"b" * 80, 160, 1, 1),
amine@244 1351 slice(80, None),
amine@194 1352 0.5,
amine@194 1353 b"b" * 80,
amine@194 1354 ),
amine@194 1355 second_half_negative=(
amine@244 1356 AudioRegion(b"a" * 80 + b"b" * 80, 160, 1, 1),
amine@244 1357 slice(-80, None),
amine@194 1358 0.5,
amine@194 1359 b"b" * 80,
amine@194 1360 ),
amine@194 1361 middle=(
amine@244 1362 AudioRegion(b"a" * 80 + b"b" * 80, 160, 1, 1),
amine@244 1363 slice(160 // 5, 160 // 4 * 3),
amine@194 1364 0.2,
amine@194 1365 b"a" * 48 + b"b" * 40,
amine@194 1366 ),
amine@194 1367 middle_negative=(
amine@244 1368 AudioRegion(b"a" * 80 + b"b" * 80, 160, 1, 1),
amine@244 1369 slice(-160 // 5 * 4, -160 // 4),
amine@194 1370 0.2,
amine@194 1371 b"a" * 48 + b"b" * 40,
amine@194 1372 ),
amine@194 1373 middle_sw2=(
amine@244 1374 AudioRegion(b"a" * 160 + b"b" * 160, 160, 2, 1),
amine@244 1375 slice(160 // 5, 160 // 4 * 3),
amine@194 1376 0.2,
amine@194 1377 b"a" * 96 + b"b" * 80,
amine@194 1378 ),
amine@194 1379 middle_ch2=(
amine@244 1380 AudioRegion(b"a" * 160 + b"b" * 160, 160, 1, 2),
amine@244 1381 slice(160 // 5, 160 // 4 * 3),
amine@194 1382 0.2,
amine@194 1383 b"a" * 96 + b"b" * 80,
amine@194 1384 ),
amine@194 1385 middle_sw2_ch2=(
amine@244 1386 AudioRegion(b"a" * 320 + b"b" * 320, 160, 2, 2),
amine@244 1387 slice(160 // 5, 160 // 4 * 3),
amine@194 1388 0.2,
amine@194 1389 b"a" * 192 + b"b" * 160,
amine@194 1390 ),
amine@194 1391 but_first_sample=(
amine@244 1392 AudioRegion(b"a" * 4000 + b"b" * 4000, 8000, 1, 1),
amine@194 1393 slice(1, None),
amine@244 1394 1 / 8000,
amine@244 1395 b"a" * (4000 - 1) + b"b" * 4000,
amine@194 1396 ),
amine@194 1397 but_first_sample_negative=(
amine@244 1398 AudioRegion(b"a" * 4000 + b"b" * 4000, 8000, 1, 1),
amine@244 1399 slice(-7999, None),
amine@244 1400 1 / 8000,
amine@244 1401 b"a" * (4000 - 1) + b"b" * 4000,
amine@194 1402 ),
amine@194 1403 but_last_sample=(
amine@244 1404 AudioRegion(b"a" * 4000 + b"b" * 4000, 8000, 1, 1),
amine@244 1405 slice(0, 7999),
amine@194 1406 0,
amine@244 1407 b"a" * 4000 + b"b" * (4000 - 1),
amine@194 1408 ),
amine@194 1409 but_last_sample_negative=(
amine@244 1410 AudioRegion(b"a" * 4000 + b"b" * 4000, 8000, 1, 1),
amine@194 1411 slice(0, -1),
amine@194 1412 0,
amine@244 1413 b"a" * 4000 + b"b" * (4000 - 1),
amine@194 1414 ),
amine@194 1415 big_negative_start=(
amine@244 1416 AudioRegion(b"a" * 160, 160, 1, 1),
amine@244 1417 slice(-1600, None),
amine@194 1418 0,
amine@194 1419 b"a" * 160,
amine@194 1420 ),
amine@194 1421 big_negative_stop=(
amine@244 1422 AudioRegion(b"a" * 160, 160, 1, 1),
amine@244 1423 slice(None, -1600),
amine@194 1424 0,
amine@194 1425 b"",
amine@194 1426 ),
amine@299 1427 empty=(
amine@299 1428 AudioRegion(b"a" * 80 + b"b" * 80, 160, 1, 1),
amine@299 1429 slice(0, 0),
amine@299 1430 0,
amine@299 1431 b"",
amine@299 1432 ),
amine@194 1433 empty_start_stop_reversed=(
amine@244 1434 AudioRegion(b"a" * 80 + b"b" * 80, 160, 1, 1),
amine@244 1435 slice(80, 40),
amine@244 1436 0.5,
amine@194 1437 b"",
amine@194 1438 ),
amine@194 1439 empty_big_positive_start=(
amine@244 1440 AudioRegion(b"a" * 80 + b"b" * 80, 160, 1, 1),
amine@244 1441 slice(1600, 3000),
amine@244 1442 10,
amine@194 1443 b"",
amine@194 1444 ),
amine@194 1445 empty_negative_reversed=(
amine@244 1446 AudioRegion(b"a" * 80 + b"b" * 80, 160, 1, 1),
amine@244 1447 slice(-16, -32),
amine@194 1448 0.9,
amine@194 1449 b"",
amine@194 1450 ),
amine@194 1451 empty_big_negative_stop=(
amine@244 1452 AudioRegion(b"a" * 80 + b"b" * 80, 160, 1, 1),
amine@194 1453 slice(0, -2000),
amine@194 1454 0,
amine@194 1455 b"",
amine@194 1456 ),
amine@230 1457 arbitrary_sampling_rate=(
amine@244 1458 AudioRegion(b"a" * 124 + b"b" * 376, 1235, 1, 1),
amine@231 1459 slice(100, 200),
amine@231 1460 100 / 1235,
amine@231 1461 b"a" * 24 + b"b" * 76,
amine@231 1462 ),
amine@231 1463 arbitrary_sampling_rate_middle_sw2_ch2=(
amine@244 1464 AudioRegion(b"a" * 124 + b"b" * 376, 1235, 2, 2),
amine@231 1465 slice(25, 50),
amine@231 1466 25 / 1235,
amine@231 1467 b"a" * 24 + b"b" * 76,
amine@231 1468 ),
amine@231 1469 )
amine@299 1470 def test_region_sample_slicing(
amine@299 1471 self, region, slice_, time_shift, expected_data
amine@299 1472 ):
amine@231 1473 sub_region = region[slice_]
amine@231 1474 self.assertEqual(bytes(sub_region), expected_data)
amine@231 1475
amine@231 1476 @genty_dataset(
amine@88 1477 simple=(8000, 1, 1),
amine@88 1478 stereo_sw_2=(8000, 2, 2),
amine@229 1479 arbitrary_sr_multichannel=(5413, 2, 3),
amine@88 1480 )
amine@88 1481 def test_concatenation(self, sampling_rate, sample_width, channels):
amine@88 1482
amine@88 1483 region_1, region_2 = _make_random_length_regions(
amine@88 1484 [b"a", b"b"], sampling_rate, sample_width, channels
amine@88 1485 )
amine@88 1486 expected_duration = region_1.duration + region_2.duration
amine@88 1487 expected_data = bytes(region_1) + bytes(region_2)
amine@88 1488 concat_region = region_1 + region_2
amine@299 1489 self.assertAlmostEqual(
amine@299 1490 concat_region.duration, expected_duration, places=6
amine@299 1491 )
amine@88 1492 self.assertEqual(bytes(concat_region), expected_data)
amine@88 1493
amine@88 1494 @genty_dataset(
amine@88 1495 simple=(8000, 1, 1),
amine@88 1496 stereo_sw_2=(8000, 2, 2),
amine@229 1497 arbitrary_sr_multichannel=(5413, 2, 3),
amine@88 1498 )
amine@88 1499 def test_concatenation_many(self, sampling_rate, sample_width, channels):
amine@88 1500
amine@88 1501 regions = _make_random_length_regions(
amine@88 1502 [b"a", b"b", b"c"], sampling_rate, sample_width, channels
amine@88 1503 )
amine@88 1504 expected_duration = sum(r.duration for r in regions)
amine@88 1505 expected_data = b"".join(bytes(r) for r in regions)
amine@88 1506 concat_region = sum(regions)
amine@88 1507
amine@299 1508 self.assertAlmostEqual(
amine@299 1509 concat_region.duration, expected_duration, places=6
amine@299 1510 )
amine@88 1511 self.assertEqual(bytes(concat_region), expected_data)
amine@88 1512
amine@88 1513 def test_concatenation_different_sampling_rate_error(self):
amine@88 1514
amine@244 1515 region_1 = AudioRegion(b"a" * 100, 8000, 1, 1)
amine@244 1516 region_2 = AudioRegion(b"b" * 100, 3000, 1, 1)
amine@88 1517
amine@88 1518 with self.assertRaises(ValueError) as val_err:
amine@88 1519 region_1 + region_2
amine@88 1520 self.assertEqual(
amine@88 1521 "Can only concatenate AudioRegions of the same "
amine@88 1522 "sampling rate (8000 != 3000)",
amine@88 1523 str(val_err.exception),
amine@88 1524 )
amine@88 1525
amine@88 1526 def test_concatenation_different_sample_width_error(self):
amine@88 1527
amine@244 1528 region_1 = AudioRegion(b"a" * 100, 8000, 2, 1)
amine@244 1529 region_2 = AudioRegion(b"b" * 100, 8000, 4, 1)
amine@88 1530
amine@88 1531 with self.assertRaises(ValueError) as val_err:
amine@88 1532 region_1 + region_2
amine@88 1533 self.assertEqual(
amine@299 1534 "Can only concatenate AudioRegions of the same "
amine@299 1535 "sample width (2 != 4)",
amine@88 1536 str(val_err.exception),
amine@88 1537 )
amine@88 1538
amine@88 1539 def test_concatenation_different_number_of_channels_error(self):
amine@88 1540
amine@244 1541 region_1 = AudioRegion(b"a" * 100, 8000, 1, 1)
amine@244 1542 region_2 = AudioRegion(b"b" * 100, 8000, 1, 2)
amine@88 1543
amine@88 1544 with self.assertRaises(ValueError) as val_err:
amine@88 1545 region_1 + region_2
amine@88 1546 self.assertEqual(
amine@88 1547 "Can only concatenate AudioRegions of the same "
amine@88 1548 "number of channels (1 != 2)",
amine@88 1549 str(val_err.exception),
amine@88 1550 )
amine@196 1551
amine@196 1552 @genty_dataset(
amine@245 1553 simple=(0.01, 0.03, 240, 30),
amine@245 1554 rounded_len_floor=(0.00575, 0.01725, 138, 17),
amine@245 1555 rounded_len_ceil=(0.00625, 0.01875, 150, 19),
amine@196 1556 )
amine@196 1557 def test_multiplication(
amine@245 1558 self, duration, expected_duration, expected_len, expected_len_ms
amine@196 1559 ):
amine@196 1560 sw = 2
amine@196 1561 data = b"0" * int(duration * 8000 * sw)
amine@244 1562 region = AudioRegion(data, 8000, sw, 1)
amine@196 1563 m_region = 1 * region * 3
amine@196 1564 self.assertEqual(bytes(m_region), data * 3)
amine@196 1565 self.assertEqual(m_region.sr, 8000)
amine@196 1566 self.assertEqual(m_region.sw, 2)
amine@196 1567 self.assertEqual(m_region.ch, 1)
amine@196 1568 self.assertEqual(m_region.duration, expected_duration)
amine@245 1569 self.assertEqual(len(m_region), expected_len)
amine@245 1570 self.assertEqual(m_region.len, expected_len)
amine@245 1571 self.assertEqual(m_region.s.len, expected_duration)
amine@245 1572 self.assertEqual(len(m_region.ms), expected_len_ms)
amine@245 1573 self.assertEqual(m_region.ms.len, expected_len_ms)
amine@197 1574
amine@198 1575 @genty_dataset(_str=("x", "str"), _float=(1.4, "float"))
amine@197 1576 def test_multiplication_non_int(self, factor, _type):
amine@197 1577 with self.assertRaises(TypeError) as type_err:
amine@244 1578 AudioRegion(b"0" * 80, 8000, 1, 1) * factor
amine@197 1579 err_msg = "Can't multiply AudioRegion by a non-int of type '{}'"
amine@197 1580 self.assertEqual(err_msg.format(_type), str(type_err.exception))
amine@254 1581
amine@254 1582 @genty_dataset(
amine@254 1583 simple=([b"a" * 80, b"b" * 80],),
amine@254 1584 extra_samples_1=([b"a" * 31, b"b" * 31, b"c" * 30],),
amine@254 1585 extra_samples_2=([b"a" * 31, b"b" * 30, b"c" * 30],),
amine@254 1586 extra_samples_3=([b"a" * 11, b"b" * 11, b"c" * 10, b"c" * 10],),
amine@254 1587 )
amine@252 1588 def test_truediv(self, data):
amine@254 1589
amine@252 1590 region = AudioRegion(b"".join(data), 80, 1, 1)
amine@252 1591
amine@252 1592 sub_regions = region / len(data)
amine@252 1593 for data_i, region in zip(data, sub_regions):
amine@252 1594 self.assertEqual(len(data_i), len(bytes(region)))
amine@254 1595
amine@254 1596 @genty_dataset(
amine@254 1597 mono_sw_1=(b"a" * 10, 1, 1, "b", [97] * 10),
amine@254 1598 mono_sw_2=(b"a" * 10, 2, 1, "h", [24929] * 5),
amine@254 1599 mono_sw_4=(b"a" * 8, 4, 1, "i", [1633771873] * 2),
amine@254 1600 stereo_sw_1=(b"ab" * 5, 1, 2, "b", [[97] * 5, [98] * 5]),
amine@254 1601 )
amine@254 1602 def test_samples(self, data, sample_width, channels, fmt, expected):
amine@254 1603
amine@254 1604 region = AudioRegion(data, 10, sample_width, channels)
amine@254 1605 if isinstance(expected[0], list):
amine@254 1606 expected = [array_(fmt, exp) for exp in expected]
amine@254 1607 else:
amine@254 1608 expected = array_(fmt, expected)
amine@254 1609 samples = region.samples
amine@254 1610 equal = samples == expected
amine@254 1611 try:
amine@254 1612 # for numpy
amine@254 1613 equal = equal.all()
amine@254 1614 except:
amine@254 1615 pass
amine@254 1616 self.assertTrue(equal)