Mercurial > hg > auditok
view tests/test_util.py @ 357:96adb05e3a07
Add tests for make_channel_selector
author | Amine Sehili <amine.sehili@gmail.com> |
---|---|
date | Wed, 01 Apr 2020 21:31:06 +0200 |
parents | 5732edbfae30 |
children | 5133fdc926fb |
line wrap: on
line source
import unittest from unittest import TestCase from unittest.mock import patch import math from array import array as array_ from genty import genty, genty_dataset from auditok.util import ( AudioEnergyValidator, make_duration_formatter, make_channel_selector, ) from auditok import signal as signal_ from auditok import signal_numpy from auditok.exceptions import TimeFormatError def _sample_generator(*data_buffers): """ Takes a list of many mono audio data buffers and makes a sample generator of interleaved audio samples, one sample from each channel. The resulting generator can be used to build a multichannel audio buffer. >>> gen = _sample_generator("abcd", "ABCD") >>> list(gen) ["a", "A", 1, 1, "c", "C", "d", "D"] """ frame_gen = zip(*data_buffers) return (sample for frame in frame_gen for sample in frame) def _generate_pure_tone( frequency, duration_sec=1, sampling_rate=16000, sample_width=2, volume=1e4 ): """ Generates a pure tone with the given frequency. """ assert frequency <= sampling_rate / 2 max_value = (2 ** (sample_width * 8) // 2) - 1 if volume > max_value: volume = max_value fmt = signal_.FORMAT[sample_width] total_samples = int(sampling_rate * duration_sec) step = frequency / sampling_rate two_pi_step = 2 * math.pi * step data = array_( fmt, ( int(math.sin(two_pi_step * i) * volume) for i in range(total_samples) ), ) return data PURE_TONE_DICT = { freq: _generate_pure_tone(freq, 1, 16000, 2) for freq in (400, 800, 1600) } PURE_TONE_DICT.update( { freq: _generate_pure_tone(freq, 0.1, 16000, 2) for freq in (600, 1150, 2400, 7220) } ) @genty class TestFunctions(TestCase): def setUp(self): self.data = b"012345679ABC" @genty_dataset( only_seconds=("%S", 5400, "5400.000"), only_millis=("%I", 5400, "5400000"), full=("%h:%m:%s.%i", 3725.365, "01:02:05.365"), full_zero_hours=("%h:%m:%s.%i", 1925.075, "00:32:05.075"), full_zero_minutes=("%h:%m:%s.%i", 3659.075, "01:00:59.075"), full_zero_seconds=("%h:%m:%s.%i", 3720.075, "01:02:00.075"), full_zero_millis=("%h:%m:%s.%i", 3725, "01:02:05.000"), duplicate_directive=( "%h %h:%m:%s.%i %s", 3725.365, "01 01:02:05.365 05", ), no_millis=("%h:%m:%s", 3725, "01:02:05"), no_seconds=("%h:%m", 3725, "01:02"), no_minutes=("%h", 3725, "01"), no_hours=("%m:%s.%i", 3725, "02:05.000"), ) def test_make_duration_formatter(self, fmt, duration, expected): formatter = make_duration_formatter(fmt) result = formatter(duration) self.assertEqual(result, expected) @genty_dataset( duplicate_only_seconds=("%S %S",), duplicate_only_millis=("%I %I",), unknown_directive=("%x",), ) def test_make_duration_formatter_error(self, fmt): with self.assertRaises(TimeFormatError): make_duration_formatter(fmt) @genty_dataset( int8_1channel_select_0=( 1, 1, 0, [48, 49, 50, 51, 52, 53, 54, 55, 57, 65, 66, 67], ), int8_2channel_select_0=(1, 2, 0, [48, 50, 52, 54, 57, 66]), int8_3channel_select_0=(1, 3, 0, [48, 51, 54, 65]), int8_3channel_select_1=(1, 3, 1, [49, 52, 55, 66]), int8_3channel_select_2=(1, 3, 2, [50, 53, 57, 67]), int8_4channel_select_0=(1, 4, 0, [48, 52, 57]), int16_1channel_select_0=( 2, 1, 0, [12592, 13106, 13620, 14134, 16697, 17218], ), int16_2channel_select_0=(2, 2, 0, [12592, 13620, 16697]), int16_2channel_select_1=(2, 2, 1, [13106, 14134, 17218]), int16_3channel_select_0=(2, 3, 0, [12592, 14134]), int16_3channel_select_1=(2, 3, 1, [13106, 16697]), int16_3channel_select_2=(2, 3, 2, [13620, 17218]), int32_1channel_select_0=(4, 1, 0, [858927408, 926299444, 1128415545],), int32_3channel_select_0=(4, 3, 0, [858927408]), int32_3channel_select_1=(4, 3, 1, [926299444]), int32_3channel_select_2=(4, 3, 2, [1128415545]), ) def test_make_channel_selector_one_channel( self, sample_width, channels, selected, expected ): # force using signal functions with standard python implementation with patch("auditok.util.signal", signal_): selector = make_channel_selector(sample_width, channels, selected) result = selector(self.data) fmt = signal_.FORMAT[sample_width] expected = array_(fmt, expected) if channels == 1: expected = bytes(expected) self.assertEqual(result, expected) # Use signal functions with numpy implementation with patch("auditok.util.signal", signal_numpy): selector = make_channel_selector(sample_width, channels, selected) resutl_numpy = selector(self.data) expected = array_(fmt, expected) if channels == 1: expected = bytes(expected) self.assertEqual(resutl_numpy, expected) else: self.assertTrue(all(resutl_numpy == expected)) @genty class TestAudioEnergyValidator(TestCase): @genty_dataset( mono_valid_uc_None=([350, 400], 1, None, True), mono_valid_uc_any=([350, 400], 1, "any", True), mono_valid_uc_0=([350, 400], 1, 0, True), mono_valid_uc_mix=([350, 400], 1, "mix", True), # previous cases are all the same since we have mono audio mono_invalid_uc_None=([300, 300], 1, None, False), stereo_valid_uc_None=([300, 400, 350, 300], 2, None, True), stereo_valid_uc_any=([300, 400, 350, 300], 2, "any", True), stereo_valid_uc_mix=([300, 400, 350, 300], 2, "mix", True), stereo_valid_uc_avg=([300, 400, 350, 300], 2, "avg", True), stereo_valid_uc_average=([300, 400, 300, 300], 2, "average", True), stereo_valid_uc_mix_with_null_channel=( [634, 0, 634, 0], 2, "mix", True, ), stereo_valid_uc_0=([320, 100, 320, 100], 2, 0, True), stereo_valid_uc_1=([100, 320, 100, 320], 2, 1, True), stereo_invalid_uc_None=([280, 100, 280, 100], 2, None, False), stereo_invalid_uc_any=([280, 100, 280, 100], 2, "any", False), stereo_invalid_uc_mix=([400, 200, 400, 200], 2, "mix", False), stereo_invalid_uc_0=([300, 400, 300, 400], 2, 0, False), stereo_invalid_uc_1=([400, 300, 400, 300], 2, 1, False), zeros=([0, 0, 0, 0], 2, None, False), ) def test_audio_energy_validator( self, data, channels, use_channel, expected ): data = array_("h", data) sample_width = 2 energy_threshold = 50 validator = AudioEnergyValidator( energy_threshold, sample_width, channels, use_channel ) if expected: self.assertTrue(validator.is_valid(data)) else: self.assertFalse(validator.is_valid(data)) if __name__ == "__main__": unittest.main()