annotate tests/test_io.py @ 403:996948ada980

Update tests
author Amine Sehili <amine.sehili@gmail.com>
date Sun, 26 May 2024 22:43:08 +0200
parents 323d59b404a2
children f56b4d8adfb8
rev   line source
amine@403 1 import filecmp
amine@403 2 import math
amine@106 3 import os
amine@106 4 import sys
amine@107 5 from array import array
amine@133 6 from tempfile import NamedTemporaryFile, TemporaryDirectory
amine@403 7 from unittest.mock import Mock, patch
amine@403 8
amine@400 9 import pytest
amine@403 10 from test_util import PURE_TONE_DICT, _generate_pure_tone, _sample_generator
amine@403 11
amine@110 12 from auditok.io import (
amine@121 13 AudioIOError,
amine@110 14 AudioParameterError,
amine@126 15 BufferAudioSource,
amine@162 16 RawAudioSource,
amine@403 17 StdinAudioSource,
amine@162 18 WaveAudioSource,
amine@403 19 _get_audio_parameters,
amine@143 20 _guess_audio_format,
amine@126 21 _load_raw,
amine@129 22 _load_wave,
amine@131 23 _load_with_pydub,
amine@111 24 _save_raw,
amine@110 25 _save_wave,
amine@141 26 _save_with_pydub,
amine@403 27 check_audio_data,
amine@403 28 from_file,
amine@403 29 get_audio_source,
amine@135 30 to_file,
amine@110 31 )
amine@403 32 from auditok.signal import FORMAT
amine@106 33
amine@120 34 AUDIO_PARAMS_SHORT = {"sr": 16000, "sw": 2, "ch": 1}
amine@106 35
amine@106 36
amine@400 37 @pytest.mark.parametrize(
amine@400 38 "data, sample_width, channels, valid",
amine@400 39 [
amine@400 40 (b"\0" * 113, 1, 1, True), # valid_mono
amine@400 41 (b"\0" * 160, 1, 2, True), # valid_stereo
amine@400 42 (b"\0" * 113, 2, 1, False), # invalid_mono_sw_2
amine@400 43 (b"\0" * 113, 1, 2, False), # invalid_stereo_sw_1
amine@400 44 (b"\0" * 158, 2, 2, False), # invalid_stereo_sw_2
amine@400 45 ],
amine@400 46 ids=[
amine@400 47 "valid_mono",
amine@400 48 "valid_stereo",
amine@400 49 "invalid_mono_sw_2",
amine@400 50 "invalid_stereo_sw_1",
amine@400 51 "invalid_stereo_sw_2",
amine@400 52 ],
amine@400 53 )
amine@400 54 def test_check_audio_data(data, sample_width, channels, valid):
amine@400 55 if not valid:
amine@400 56 with pytest.raises(AudioParameterError):
amine@400 57 check_audio_data(data, sample_width, channels)
amine@400 58 else:
amine@400 59 assert check_audio_data(data, sample_width, channels) is None
amine@400 60
amine@400 61
amine@400 62 @pytest.mark.parametrize(
amine@400 63 "fmt, filename, expected",
amine@400 64 [
amine@400 65 ("wav", "filename.wav", "wav"), # extention_and_format_same
amine@400 66 ("wav", "filename.mp3", "wav"), # extention_and_format_different
amine@400 67 (None, "filename.wav", "wav"), # extention_no_format
amine@400 68 ("wav", "filename", "wav"), # format_no_extension
amine@400 69 (None, "filename", None), # no_format_no_extension
amine@400 70 ("wave", "filename", "wav"), # wave_as_wav
amine@400 71 (None, "filename.wave", "wav"), # wave_as_wav_extension
amine@400 72 ],
amine@400 73 ids=[
amine@400 74 "extention_and_format_same",
amine@400 75 "extention_and_format_different",
amine@400 76 "extention_no_format",
amine@400 77 "format_no_extension",
amine@400 78 "no_format_no_extension",
amine@400 79 "wave_as_wav",
amine@400 80 "wave_as_wav_extension",
amine@400 81 ],
amine@400 82 )
amine@400 83 def test_guess_audio_format(fmt, filename, expected):
amine@400 84 result = _guess_audio_format(fmt, filename)
amine@400 85 assert result == expected
amine@400 86
amine@400 87
amine@400 88 def test_get_audio_parameters_short_params():
amine@400 89 expected = (8000, 2, 1)
amine@400 90 params = dict(zip(("sr", "sw", "ch"), expected))
amine@400 91 result = _get_audio_parameters(params)
amine@400 92 assert result == expected
amine@400 93
amine@400 94
amine@400 95 def test_get_audio_parameters_long_params():
amine@400 96 expected = (8000, 2, 1)
amine@400 97 params = dict(
amine@400 98 zip(
amine@400 99 ("sampling_rate", "sample_width", "channels", "use_channel"),
amine@400 100 expected,
amine@400 101 )
amine@108 102 )
amine@400 103 result = _get_audio_parameters(params)
amine@400 104 assert result == expected
amine@108 105
amine@110 106
amine@400 107 def test_get_audio_parameters_long_params_shadow_short_ones():
amine@400 108 expected = (8000, 2, 1)
amine@400 109 params = dict(zip(("sampling_rate", "sample_width", "channels"), expected))
amine@400 110 params.update(dict(zip(("sr", "sw", "ch"), "xxx")))
amine@400 111 result = _get_audio_parameters(params)
amine@400 112 assert result == expected
amine@143 113
amine@145 114
amine@400 115 @pytest.mark.parametrize(
amine@400 116 "values",
amine@400 117 [
amine@400 118 ("x", 2, 1), # str_sampling_rate
amine@400 119 (-8000, 2, 1), # negative_sampling_rate
amine@400 120 (8000, "x", 1), # str_sample_width
amine@400 121 (8000, -2, 1), # negative_sample_width
amine@400 122 (8000, 2, "x"), # str_channels
amine@400 123 (8000, 2, -1), # negative_channels
amine@400 124 ],
amine@400 125 ids=[
amine@400 126 "str_sampling_rate",
amine@400 127 "negative_sampling_rate",
amine@400 128 "str_sample_width",
amine@400 129 "negative_sample_width",
amine@400 130 "str_channels",
amine@400 131 "negative_channels",
amine@400 132 ],
amine@400 133 )
amine@400 134 def test_get_audio_parameters_invalid(values):
amine@400 135 params = dict(zip(("sampling_rate", "sample_width", "channels"), values))
amine@400 136 with pytest.raises(AudioParameterError):
amine@400 137 _get_audio_parameters(params)
amine@145 138
amine@145 139
amine@400 140 @pytest.mark.parametrize(
amine@400 141 "filename, audio_format, funtion_name, kwargs",
amine@400 142 [
amine@400 143 (
amine@120 144 "audio",
amine@120 145 "raw",
amine@120 146 "_load_raw",
amine@120 147 AUDIO_PARAMS_SHORT,
amine@400 148 ), # raw_with_audio_format
amine@400 149 (
amine@120 150 "audio.raw",
amine@120 151 None,
amine@120 152 "_load_raw",
amine@120 153 AUDIO_PARAMS_SHORT,
amine@400 154 ), # raw_with_extension
amine@400 155 ("audio", "wave", "_load_wave", None), # wave_with_audio_format
amine@400 156 ("audio", "wave", "_load_wave", None), # wav_with_audio_format
amine@400 157 ("audio.wav", None, "_load_wave", None), # wav_with_extension
amine@400 158 (
amine@400 159 "audio.dat",
amine@400 160 "wav",
amine@400 161 "_load_wave",
amine@400 162 None,
amine@400 163 ), # format_and_extension_both_given_a
amine@400 164 (
amine@400 165 "audio.raw",
amine@400 166 "wave",
amine@400 167 "_load_wave",
amine@400 168 None,
amine@400 169 ), # format_and_extension_both_given_b
amine@400 170 ("audio", None, "_load_with_pydub", None), # no_format_nor_extension
amine@400 171 ("audio.ogg", None, "_load_with_pydub", None), # other_formats_ogg
amine@400 172 ("audio", "webm", "_load_with_pydub", None), # other_formats_webm
amine@400 173 ],
amine@400 174 ids=[
amine@400 175 "raw_with_audio_format",
amine@400 176 "raw_with_extension",
amine@400 177 "wave_with_audio_format",
amine@400 178 "wav_with_audio_format",
amine@400 179 "wav_with_extension",
amine@400 180 "format_and_extension_both_given_a",
amine@400 181 "format_and_extension_both_given_b",
amine@400 182 "no_format_nor_extension",
amine@400 183 "other_formats_ogg",
amine@400 184 "other_formats_webm",
amine@400 185 ],
amine@400 186 )
amine@400 187 def test_from_file(filename, audio_format, funtion_name, kwargs):
amine@400 188 funtion_name = "auditok.io." + funtion_name
amine@400 189 if kwargs is None:
amine@400 190 kwargs = {}
amine@400 191 with patch(funtion_name) as patch_function:
amine@400 192 from_file(filename, audio_format, **kwargs)
amine@400 193 assert patch_function.called
amine@400 194
amine@400 195
amine@400 196 def test_from_file_large_file_raw():
amine@400 197 filename = "tests/data/test_16KHZ_mono_400Hz.raw"
amine@400 198 audio_source = from_file(
amine@400 199 filename,
amine@400 200 large_file=True,
amine@400 201 sampling_rate=16000,
amine@400 202 sample_width=2,
amine@400 203 channels=1,
amine@120 204 )
amine@400 205 assert isinstance(audio_source, RawAudioSource)
amine@120 206
amine@162 207
amine@400 208 def test_from_file_large_file_wave():
amine@400 209 filename = "tests/data/test_16KHZ_mono_400Hz.wav"
amine@400 210 audio_source = from_file(filename, large_file=True)
amine@400 211 assert isinstance(audio_source, WaveAudioSource)
amine@163 212
amine@162 213
amine@400 214 def test_from_file_large_file_compressed():
amine@400 215 filename = "tests/data/test_16KHZ_mono_400Hz.ogg"
amine@400 216 with pytest.raises(AudioIOError):
amine@400 217 from_file(filename, large_file=True)
amine@137 218
amine@121 219
amine@400 220 @pytest.mark.parametrize(
amine@400 221 "missing_param",
amine@400 222 [
amine@400 223 "sr", # missing_sampling_rate
amine@400 224 "sw", # missing_sample_width
amine@400 225 "ch", # missing_channels
amine@400 226 ],
amine@400 227 ids=["missing_sampling_rate", "missing_sample_width", "missing_channels"],
amine@400 228 )
amine@400 229 def test_from_file_missing_audio_param(missing_param):
amine@400 230 with pytest.raises(AudioParameterError):
amine@400 231 params = AUDIO_PARAMS_SHORT.copy()
amine@400 232 del params[missing_param]
amine@400 233 from_file("audio", audio_format="raw", **params)
amine@240 234
amine@400 235
amine@400 236 def test_from_file_no_pydub():
amine@400 237 with patch("auditok.io._WITH_PYDUB", False):
amine@400 238 with pytest.raises(AudioIOError):
amine@400 239 from_file("audio", "mp3")
amine@400 240
amine@400 241
amine@400 242 @pytest.mark.parametrize(
amine@400 243 "audio_format, function",
amine@400 244 [
amine@400 245 ("ogg", "from_ogg"), # ogg_first_channel
amine@400 246 ("ogg", "from_ogg"), # ogg_second_channel
amine@400 247 ("ogg", "from_ogg"), # ogg_mix
amine@400 248 ("ogg", "from_ogg"), # ogg_default
amine@400 249 ("mp3", "from_mp3"), # mp3_left_channel
amine@400 250 ("mp3", "from_mp3"), # mp3_right_channel
amine@400 251 ("flac", "from_file"), # flac_first_channel
amine@400 252 ("flac", "from_file"), # flac_second_channel
amine@400 253 ("flv", "from_flv"), # flv_left_channel
amine@400 254 ("webm", "from_file"), # webm_right_channel
amine@400 255 ],
amine@400 256 ids=[
amine@400 257 "ogg_first_channel",
amine@400 258 "ogg_second_channel",
amine@400 259 "ogg_mix",
amine@400 260 "ogg_default",
amine@400 261 "mp3_left_channel",
amine@400 262 "mp3_right_channel",
amine@400 263 "flac_first_channel",
amine@400 264 "flac_second_channel",
amine@400 265 "flv_left_channel",
amine@400 266 "webm_right_channel",
amine@400 267 ],
amine@400 268 )
amine@400 269 @patch("auditok.io._WITH_PYDUB", True)
amine@400 270 @patch("auditok.io.BufferAudioSource")
amine@400 271 def test_from_file_multichannel_audio_compressed(
amine@400 272 mock_buffer_audio_source, audio_format, function
amine@400 273 ):
amine@400 274 filename = "audio.{}".format(audio_format)
amine@400 275 segment_mock = Mock()
amine@400 276 segment_mock.sample_width = 2
amine@400 277 segment_mock.channels = 2
amine@400 278 segment_mock._data = b"abcd"
amine@400 279 with patch("auditok.io.AudioSegment.{}".format(function)) as open_func:
amine@400 280 open_func.return_value = segment_mock
amine@400 281 from_file(filename)
amine@400 282 assert open_func.called
amine@400 283
amine@400 284
amine@400 285 @pytest.mark.parametrize(
amine@400 286 "file_id, frequencies, large_file",
amine@400 287 [
amine@400 288 ("mono_400", (400,), False), # mono
amine@400 289 ("3channel_400-800-1600", (400, 800, 1600), False), # three_channel
amine@400 290 ("mono_400", (400,), True), # mono_large_file
amine@400 291 (
amine@313 292 "3channel_400-800-1600",
amine@313 293 (400, 800, 1600),
amine@313 294 True,
amine@400 295 ), # three_channel_large_file
amine@400 296 ],
amine@400 297 ids=[
amine@400 298 "mono",
amine@400 299 "three_channel",
amine@400 300 "mono_large_file",
amine@400 301 "three_channel_large_file",
amine@400 302 ],
amine@400 303 )
amine@400 304 def test_load_raw(file_id, frequencies, large_file):
amine@400 305 filename = "tests/data/test_16KHZ_{}Hz.raw".format(file_id)
amine@400 306 audio_source = _load_raw(
amine@400 307 filename, 16000, 2, len(frequencies), large_file=large_file
amine@126 308 )
amine@400 309 audio_source.open()
amine@400 310 data = audio_source.read(-1)
amine@400 311 audio_source.close()
amine@400 312 expected_class = RawAudioSource if large_file else BufferAudioSource
amine@400 313 assert isinstance(audio_source, expected_class)
amine@400 314 assert audio_source.sampling_rate == 16000
amine@400 315 assert audio_source.sample_width == 2
amine@400 316 assert audio_source.channels == len(frequencies)
amine@400 317 mono_channels = [PURE_TONE_DICT[freq] for freq in frequencies]
amine@400 318 fmt = FORMAT[audio_source.sample_width]
amine@400 319 expected = array(fmt, _sample_generator(*mono_channels)).tobytes()
amine@400 320 assert data == expected
amine@126 321
amine@128 322
amine@400 323 @pytest.mark.parametrize(
amine@400 324 "missing_param",
amine@400 325 [
amine@400 326 "sr", # missing_sampling_rate
amine@400 327 "sw", # missing_sample_width
amine@400 328 "ch", # missing_channels
amine@400 329 ],
amine@400 330 ids=["missing_sampling_rate", "missing_sample_width", "missing_channels"],
amine@400 331 )
amine@400 332 def test_load_raw_missing_audio_param(missing_param):
amine@400 333 with pytest.raises(AudioParameterError):
amine@400 334 params = AUDIO_PARAMS_SHORT.copy()
amine@400 335 del params[missing_param]
amine@400 336 srate, swidth, channels, _ = _get_audio_parameters(params)
amine@400 337 _load_raw("audio", srate, swidth, channels)
amine@400 338
amine@400 339
amine@400 340 @pytest.mark.parametrize(
amine@400 341 "file_id, frequencies, large_file",
amine@400 342 [
amine@400 343 ("mono_400", (400,), False), # mono
amine@400 344 ("3channel_400-800-1600", (400, 800, 1600), False), # three_channel
amine@400 345 ("mono_400", (400,), True), # mono_large_file
amine@400 346 (
amine@313 347 "3channel_400-800-1600",
amine@313 348 (400, 800, 1600),
amine@313 349 True,
amine@400 350 ), # three_channel_large_file
amine@400 351 ],
amine@400 352 ids=[
amine@400 353 "mono",
amine@400 354 "three_channel",
amine@400 355 "mono_large_file",
amine@400 356 "three_channel_large_file",
amine@400 357 ],
amine@400 358 )
amine@400 359 def test_load_wave(file_id, frequencies, large_file):
amine@400 360 filename = "tests/data/test_16KHZ_{}Hz.wav".format(file_id)
amine@400 361 audio_source = _load_wave(filename, large_file=large_file)
amine@400 362 audio_source.open()
amine@400 363 data = audio_source.read(-1)
amine@400 364 audio_source.close()
amine@400 365 expected_class = WaveAudioSource if large_file else BufferAudioSource
amine@400 366 assert isinstance(audio_source, expected_class)
amine@400 367 assert audio_source.sampling_rate == 16000
amine@400 368 assert audio_source.sample_width == 2
amine@400 369 assert audio_source.channels == len(frequencies)
amine@400 370 mono_channels = [PURE_TONE_DICT[freq] for freq in frequencies]
amine@400 371 fmt = FORMAT[audio_source.sample_width]
amine@400 372 expected = array(fmt, _sample_generator(*mono_channels)).tobytes()
amine@400 373 assert data == expected
amine@400 374
amine@400 375
amine@400 376 @pytest.mark.parametrize(
amine@400 377 "audio_format, channels, function",
amine@400 378 [
amine@400 379 ("ogg", 2, "from_ogg"), # ogg_default_first_channel
amine@400 380 ("ogg", 1, "from_ogg"), # ogg_first_channel
amine@400 381 ("ogg", 2, "from_ogg"), # ogg_second_channel
amine@400 382 ("ogg", 3, "from_ogg"), # ogg_mix_channels
amine@400 383 ("mp3", 1, "from_mp3"), # mp3_left_channel
amine@400 384 ("mp3", 2, "from_mp3"), # mp3_right_channel
amine@400 385 ("mp3", 3, "from_mp3"), # mp3_mix_channels
amine@400 386 ("flac", 2, "from_file"), # flac_first_channel
amine@400 387 ("flac", 2, "from_file"), # flac_second_channel
amine@400 388 ("flv", 1, "from_flv"), # flv_left_channel
amine@400 389 ("webm", 2, "from_file"), # webm_right_channel
amine@400 390 ("webm", 4, "from_file"), # webm_mix_channels
amine@400 391 ],
amine@400 392 ids=[
amine@400 393 "ogg_default_first_channel",
amine@400 394 "ogg_first_channel",
amine@400 395 "ogg_second_channel",
amine@400 396 "ogg_mix_channels",
amine@400 397 "mp3_left_channel",
amine@400 398 "mp3_right_channel",
amine@400 399 "mp3_mix_channels",
amine@400 400 "flac_first_channel",
amine@400 401 "flac_second_channel",
amine@400 402 "flv_left_channel",
amine@400 403 "webm_right_channel",
amine@400 404 "webm_mix_channels",
amine@400 405 ],
amine@400 406 )
amine@400 407 @patch("auditok.io._WITH_PYDUB", True)
amine@400 408 @patch("auditok.io.BufferAudioSource")
amine@400 409 def test_load_with_pydub(
amine@400 410 mock_buffer_audio_source, audio_format, channels, function
amine@400 411 ):
amine@400 412 filename = "audio.{}".format(audio_format)
amine@400 413 segment_mock = Mock()
amine@400 414 segment_mock.sample_width = 2
amine@400 415 segment_mock.channels = channels
amine@400 416 segment_mock._data = b"abcdefgh"
amine@400 417 with patch("auditok.io.AudioSegment.{}".format(function)) as open_func:
amine@400 418 open_func.return_value = segment_mock
amine@400 419 _load_with_pydub(filename, audio_format)
amine@400 420 assert open_func.called
amine@400 421
amine@400 422
amine@400 423 @pytest.mark.parametrize(
amine@400 424 "filename, frequencies",
amine@400 425 [
amine@400 426 ("mono_400Hz.raw", (400,)), # mono
amine@400 427 ("3channel_400-800-1600Hz.raw", (400, 800, 1600)), # three_channel
amine@400 428 ],
amine@400 429 ids=["mono", "three_channel"],
amine@400 430 )
amine@400 431 def test_save_raw(filename, frequencies):
amine@400 432 filename = "tests/data/test_16KHZ_{}".format(filename)
amine@400 433 sample_width = 2
amine@400 434 fmt = FORMAT[sample_width]
amine@400 435 mono_channels = [PURE_TONE_DICT[freq] for freq in frequencies]
amine@400 436 data = array(fmt, _sample_generator(*mono_channels)).tobytes()
amine@400 437 tmpfile = NamedTemporaryFile()
amine@400 438 _save_raw(data, tmpfile.name)
amine@400 439 assert filecmp.cmp(tmpfile.name, filename, shallow=False)
amine@400 440
amine@400 441
amine@400 442 @pytest.mark.parametrize(
amine@400 443 "filename, frequencies",
amine@400 444 [
amine@400 445 ("mono_400Hz.wav", (400,)), # mono
amine@400 446 ("3channel_400-800-1600Hz.wav", (400, 800, 1600)), # three_channel
amine@400 447 ],
amine@400 448 ids=["mono", "three_channel"],
amine@400 449 )
amine@400 450 def test_save_wave(filename, frequencies):
amine@400 451 filename = "tests/data/test_16KHZ_{}".format(filename)
amine@400 452 sampling_rate = 16000
amine@400 453 sample_width = 2
amine@400 454 channels = len(frequencies)
amine@400 455 fmt = FORMAT[sample_width]
amine@400 456 mono_channels = [PURE_TONE_DICT[freq] for freq in frequencies]
amine@400 457 data = array(fmt, _sample_generator(*mono_channels)).tobytes()
amine@400 458 tmpfile = NamedTemporaryFile()
amine@400 459 _save_wave(data, tmpfile.name, sampling_rate, sample_width, channels)
amine@400 460 assert filecmp.cmp(tmpfile.name, filename, shallow=False)
amine@400 461
amine@400 462
amine@400 463 @pytest.mark.parametrize(
amine@400 464 "missing_param",
amine@400 465 [
amine@400 466 "sr", # missing_sampling_rate
amine@400 467 "sw", # missing_sample_width
amine@400 468 "ch", # missing_channels
amine@400 469 ],
amine@400 470 ids=["missing_sampling_rate", "missing_sample_width", "missing_channels"],
amine@400 471 )
amine@400 472 def test_save_wave_missing_audio_param(missing_param):
amine@400 473 with pytest.raises(AudioParameterError):
amine@400 474 params = AUDIO_PARAMS_SHORT.copy()
amine@400 475 del params[missing_param]
amine@400 476 srate, swidth, channels, _ = _get_audio_parameters(params)
amine@400 477 _save_wave(b"\0\0", "audio", srate, swidth, channels)
amine@400 478
amine@400 479
amine@400 480 def test_save_with_pydub():
amine@400 481 with patch("auditok.io.AudioSegment.export") as export:
amine@400 482 tmpdir = TemporaryDirectory()
amine@400 483 filename = os.path.join(tmpdir.name, "audio.ogg")
amine@400 484 _save_with_pydub(b"\0\0", filename, "ogg", 16000, 2, 1)
amine@400 485 assert export.called
amine@400 486 tmpdir.cleanup()
amine@400 487
amine@400 488
amine@400 489 @pytest.mark.parametrize(
amine@400 490 "filename, audio_format",
amine@400 491 [
amine@400 492 ("audio", "raw"), # raw_with_audio_format
amine@400 493 ("audio.raw", None), # raw_with_extension
amine@400 494 ("audio.mp3", "raw"), # raw_with_audio_format_and_extension
amine@400 495 ("audio", None), # raw_no_audio_format_nor_extension
amine@400 496 ],
amine@400 497 ids=[
amine@400 498 "raw_with_audio_format",
amine@400 499 "raw_with_extension",
amine@400 500 "raw_with_audio_format_and_extension",
amine@400 501 "raw_no_audio_format_nor_extension",
amine@400 502 ],
amine@400 503 )
amine@400 504 def test_to_file_raw(filename, audio_format):
amine@400 505 exp_filename = "tests/data/test_16KHZ_mono_400Hz.raw"
amine@400 506 tmpdir = TemporaryDirectory()
amine@400 507 filename = os.path.join(tmpdir.name, filename)
amine@400 508 data = PURE_TONE_DICT[400].tobytes()
amine@400 509 to_file(data, filename, audio_format=audio_format)
amine@400 510 assert filecmp.cmp(filename, exp_filename, shallow=False)
amine@400 511 tmpdir.cleanup()
amine@400 512
amine@400 513
amine@400 514 @pytest.mark.parametrize(
amine@400 515 "filename, audio_format",
amine@400 516 [
amine@400 517 ("audio", "wav"), # wav_with_audio_format
amine@400 518 ("audio.wav", None), # wav_with_extension
amine@400 519 ("audio.mp3", "wav"), # wav_with_audio_format_and_extension
amine@400 520 ("audio", "wave"), # wave_with_audio_format
amine@400 521 ("audio.wave", None), # wave_with_extension
amine@400 522 ("audio.mp3", "wave"), # wave_with_audio_format_and_extension
amine@400 523 ],
amine@400 524 ids=[
amine@400 525 "wav_with_audio_format",
amine@400 526 "wav_with_extension",
amine@400 527 "wav_with_audio_format_and_extension",
amine@400 528 "wave_with_audio_format",
amine@400 529 "wave_with_extension",
amine@400 530 "wave_with_audio_format_and_extension",
amine@400 531 ],
amine@400 532 )
amine@400 533 def test_to_file_wave(filename, audio_format):
amine@400 534 exp_filename = "tests/data/test_16KHZ_mono_400Hz.wav"
amine@400 535 tmpdir = TemporaryDirectory()
amine@400 536 filename = os.path.join(tmpdir.name, filename)
amine@400 537 data = PURE_TONE_DICT[400].tobytes()
amine@400 538 to_file(
amine@400 539 data,
amine@400 540 filename,
amine@400 541 audio_format=audio_format,
amine@400 542 sampling_rate=16000,
amine@400 543 sample_width=2,
amine@400 544 channels=1,
amine@129 545 )
amine@400 546 assert filecmp.cmp(filename, exp_filename, shallow=False)
amine@400 547 tmpdir.cleanup()
amine@129 548
amine@240 549
amine@400 550 @pytest.mark.parametrize(
amine@400 551 "missing_param",
amine@400 552 [
amine@400 553 "sr", # missing_sampling_rate
amine@400 554 "sw", # missing_sample_width
amine@400 555 "ch", # missing_channels
amine@400 556 ],
amine@400 557 ids=["missing_sampling_rate", "missing_sample_width", "missing_channels"],
amine@400 558 )
amine@400 559 def test_to_file_missing_audio_param(missing_param):
amine@400 560 params = AUDIO_PARAMS_SHORT.copy()
amine@400 561 del params[missing_param]
amine@400 562 with pytest.raises(AudioParameterError):
amine@400 563 to_file(b"\0\0", "audio", audio_format="wav", **params)
amine@400 564 with pytest.raises(AudioParameterError):
amine@400 565 to_file(b"\0\0", "audio", audio_format="mp3", **params)
amine@132 566
amine@132 567
amine@400 568 def test_to_file_no_pydub():
amine@400 569 with patch("auditok.io._WITH_PYDUB", False):
amine@400 570 with pytest.raises(AudioIOError):
amine@400 571 to_file("audio", b"", "mp3")
amine@133 572
amine@141 573
amine@400 574 @pytest.mark.parametrize(
amine@400 575 "filename, audio_format",
amine@400 576 [
amine@400 577 ("audio.ogg", None), # ogg_with_extension
amine@400 578 ("audio", "ogg"), # ogg_with_audio_format
amine@400 579 ("audio.wav", "ogg"), # ogg_format_with_wrong_extension
amine@400 580 ],
amine@400 581 ids=[
amine@400 582 "ogg_with_extension",
amine@400 583 "ogg_with_audio_format",
amine@400 584 "ogg_format_with_wrong_extension",
amine@400 585 ],
amine@400 586 )
amine@400 587 @patch("auditok.io._WITH_PYDUB", True)
amine@400 588 def test_to_file_compressed(filename, audio_format):
amine@400 589 with patch("auditok.io.AudioSegment.export") as export:
amine@133 590 tmpdir = TemporaryDirectory()
amine@133 591 filename = os.path.join(tmpdir.name, filename)
amine@400 592 to_file(b"\0\0", filename, audio_format, **AUDIO_PARAMS_SHORT)
amine@400 593 assert export.called
amine@133 594 tmpdir.cleanup()
amine@134 595
amine@138 596
amine@400 597 @pytest.mark.parametrize(
amine@400 598 "input, expected_type, extra_args",
amine@400 599 [
amine@400 600 (
amine@190 601 "tests/data/test_16KHZ_mono_400Hz.wav",
amine@190 602 BufferAudioSource,
amine@400 603 None,
amine@400 604 ), # string_wave
amine@400 605 (
amine@190 606 "tests/data/test_16KHZ_mono_400Hz.wav",
amine@190 607 WaveAudioSource,
amine@190 608 {"large_file": True},
amine@400 609 ), # string_wave_large_file
amine@400 610 ("-", StdinAudioSource, None), # stdin
amine@400 611 (
amine@400 612 "tests/data/test_16KHZ_mono_400Hz.raw",
amine@400 613 BufferAudioSource,
amine@400 614 None,
amine@400 615 ), # string_raw
amine@400 616 (
amine@190 617 "tests/data/test_16KHZ_mono_400Hz.raw",
amine@190 618 RawAudioSource,
amine@190 619 {"large_file": True},
amine@400 620 ), # string_raw_large_file
amine@400 621 (b"0" * 8000, BufferAudioSource, None), # bytes_
amine@400 622 ],
amine@400 623 ids=[
amine@400 624 "string_wave",
amine@400 625 "string_wave_large_file",
amine@400 626 "stdin",
amine@400 627 "string_raw",
amine@400 628 "string_raw_large_file",
amine@400 629 "bytes_",
amine@400 630 ],
amine@400 631 )
amine@400 632 def test_get_audio_source(input, expected_type, extra_args):
amine@400 633 kwargs = {"sampling_rate": 16000, "sample_width": 2, "channels": 1}
amine@400 634 if extra_args is not None:
amine@400 635 kwargs.update(extra_args)
amine@400 636 audio_source = get_audio_source(input, **kwargs)
amine@400 637 assert isinstance(audio_source, expected_type)
amine@403 638 assert audio_source.sampling_rate == 16000, (
amine@403 639 "Unexpected sampling rate: audio_source.sampling_rate = "
amine@403 640 + f"{audio_source.sampling_rate} instead of 16000"
amine@403 641 )
amine@403 642 assert audio_source.sr == 16000, (
amine@403 643 "Unexpected sampling rate: audio_source.sr = "
amine@403 644 + f"{audio_source.sr} instead of 16000"
amine@403 645 )
amine@403 646 assert audio_source.sample_width == 2, (
amine@403 647 "Unexpected sample width: audio_source.sample_width = "
amine@403 648 + f"{audio_source.sample_width} instead of 2"
amine@403 649 )
amine@403 650 assert audio_source.sw == 2, (
amine@403 651 "Unexpected sample width: audio_source.sw = "
amine@403 652 + f"{audio_source.sw} instead of 2"
amine@403 653 )
amine@403 654 assert audio_source.channels == 1, (
amine@403 655 "Unexpected number of channels: audio_source.channels = "
amine@403 656 + f"{audio_source.channels} instead of 1"
amine@403 657 )
amine@403 658 assert audio_source.ch == 1, (
amine@403 659 "Unexpected number of channels: audio_source.ch = "
amine@403 660 + f"{audio_source.ch} instead of 1"
amine@403 661 )
amine@403 662
amine@403 663
amine@403 664 def test_get_audio_source_alias_prams():
amine@403 665 audio_source = get_audio_source(b"0" * 1600, sr=16000, sw=2, ch=1)
amine@403 666 assert audio_source.sampling_rate == 16000, (
amine@403 667 "Unexpected sampling rate: audio_source.sampling_rate = "
amine@403 668 + f"{audio_source.sampling_rate} instead of 16000"
amine@403 669 )
amine@403 670 assert audio_source.sr == 16000, (
amine@403 671 "Unexpected sampling rate: audio_source.sr = "
amine@403 672 + f"{audio_source.sr} instead of 16000"
amine@403 673 )
amine@403 674 assert audio_source.sample_width == 2, (
amine@403 675 "Unexpected sample width: audio_source.sample_width = "
amine@403 676 + f"{audio_source.sample_width} instead of 2"
amine@403 677 )
amine@403 678 assert audio_source.sw == 2, (
amine@403 679 "Unexpected sample width: audio_source.sw = "
amine@403 680 + f"{audio_source.sw} instead of 2"
amine@403 681 )
amine@403 682 assert audio_source.channels == 1, (
amine@403 683 "Unexpected number of channels: audio_source.channels = "
amine@403 684 + f"{audio_source.channels} instead of 1"
amine@403 685 )
amine@403 686 assert audio_source.ch == 1, (
amine@403 687 "Unexpected number of channels: audio_source.ch = "
amine@403 688 + f"{audio_source.ch} instead of 1"
amine@403 689 )