amine@164: """ amine@164: @author: Amine Sehili amine@164: """ amine@400: amine@164: from array import array amine@403: amine@405: import numpy as np amine@400: import pytest amine@403: amine@164: from auditok.io import ( amine@405: AudioIOError, amine@164: AudioParameterError, amine@164: BufferAudioSource, amine@164: RawAudioSource, amine@164: WaveAudioSource, amine@164: ) amine@405: from auditok.signal import SAMPLE_WIDTH_TO_DTYPE amine@405: amine@405: amine@405: def _sample_generator(*data_buffers): amine@405: """ amine@405: Takes a list of many mono audio data buffers and makes a sample generator amine@405: of interleaved audio samples, one sample from each channel. The resulting amine@405: generator can be used to build a multichannel audio buffer. amine@405: >>> gen = _sample_generator("abcd", "ABCD") amine@405: >>> list(gen) amine@405: ["a", "A", "b", "B", "c", "C", "d", "D"] amine@405: """ amine@426: frame_gen = zip(*data_buffers) amine@405: return (sample for frame in frame_gen for sample in frame) amine@405: amine@405: amine@405: def _generate_pure_tone( amine@405: frequency, duration_sec=1, sampling_rate=16000, sample_width=2, volume=1e4 amine@405: ): amine@405: """ amine@405: Generates a pure tone with the given frequency. amine@405: """ amine@405: assert frequency <= sampling_rate / 2 amine@405: max_value = (2 ** (sample_width * 8) // 2) - 1 amine@405: if volume > max_value: amine@405: volume = max_value amine@405: dtype = SAMPLE_WIDTH_TO_DTYPE[sample_width] amine@405: total_samples = int(sampling_rate * duration_sec) amine@405: step = frequency / sampling_rate amine@405: two_pi_step = 2 * np.pi * step amine@405: data = np.array( amine@405: [int(np.sin(two_pi_step * i) * volume) for i in range(total_samples)] amine@405: ).astype(dtype) amine@405: return data amine@405: amine@405: amine@405: @pytest.fixture amine@405: def pure_tone_data(freq): amine@405: amine@405: PURE_TONE_DICT = { amine@405: freq: _generate_pure_tone(freq, 1, 16000, 2) amine@405: for freq in (400, 800, 1600) amine@405: } amine@405: PURE_TONE_DICT.update( amine@405: { amine@405: freq: _generate_pure_tone(freq, 0.1, 16000, 2) amine@405: for freq in (600, 1150, 2400, 7220) amine@405: } amine@405: ) amine@405: return PURE_TONE_DICT[freq] amine@405: amine@405: amine@405: PURE_TONE_DICT = { amine@405: freq: _generate_pure_tone(freq, 1, 16000, 2) for freq in (400, 800, 1600) amine@405: } amine@405: PURE_TONE_DICT.update( amine@405: { amine@405: freq: _generate_pure_tone(freq, 0.1, 16000, 2) amine@405: for freq in (600, 1150, 2400, 7220) amine@405: } amine@405: ) amine@164: amine@164: amine@164: def audio_source_read_all_gen(audio_source, size=None): amine@164: if size is None: amine@164: size = int(audio_source.sr * 0.1) # 100ms amine@164: while True: amine@164: data = audio_source.read(size) amine@164: if data is None: amine@164: break amine@164: yield data amine@164: amine@164: amine@400: @pytest.mark.parametrize( amine@400: "file_suffix, frequencies", amine@400: [ amine@400: ("mono_400Hz", (400,)), # mono amine@400: ("3channel_400-800-1600Hz", (400, 800, 1600)), # multichannel amine@400: ], amine@400: ids=["mono", "multichannel"], amine@400: ) amine@400: def test_BufferAudioSource_read_all(file_suffix, frequencies): amine@400: file = "tests/data/test_16KHZ_{}.raw".format(file_suffix) amine@400: with open(file, "rb") as fp: amine@400: expected = fp.read() amine@400: channels = len(frequencies) amine@400: audio_source = BufferAudioSource(expected, 16000, 2, channels) amine@400: audio_source.open() amine@400: data = audio_source.read(None) amine@400: assert data == expected amine@400: audio_source.rewind() amine@400: data = audio_source.read(-10) amine@400: assert data == expected amine@400: audio_source.close() amine@164: amine@164: amine@400: @pytest.mark.parametrize( amine@400: "file_suffix, frequencies", amine@400: [ amine@400: ("mono_400Hz", (400,)), # mono amine@400: ("3channel_400-800-1600Hz", (400, 800, 1600)), # multichannel amine@400: ], amine@400: ids=["mono", "multichannel"], amine@400: ) amine@400: def test_RawAudioSource(file_suffix, frequencies): amine@400: file = "tests/data/test_16KHZ_{}.raw".format(file_suffix) amine@400: channels = len(frequencies) amine@400: audio_source = RawAudioSource(file, 16000, 2, channels) amine@400: audio_source.open() amine@400: data_read_all = b"".join(audio_source_read_all_gen(audio_source)) amine@400: audio_source.close() amine@400: mono_channels = [PURE_TONE_DICT[freq] for freq in frequencies] amine@405: dtype = SAMPLE_WIDTH_TO_DTYPE[audio_source.sample_width] amine@405: expected = np.fromiter(_sample_generator(*mono_channels), dtype).tobytes() amine@238: amine@400: assert data_read_all == expected amine@240: amine@400: # assert read all data with None amine@400: audio_source = RawAudioSource(file, 16000, 2, channels) amine@400: audio_source.open() amine@400: data_read_all = audio_source.read(None) amine@400: audio_source.close() amine@400: assert data_read_all == expected amine@164: amine@400: # assert read all data with a negative size amine@400: audio_source = RawAudioSource(file, 16000, 2, channels) amine@400: audio_source.open() amine@400: data_read_all = audio_source.read(-10) amine@400: audio_source.close() amine@400: assert data_read_all == expected amine@238: amine@238: amine@400: @pytest.mark.parametrize( amine@400: "file_suffix, frequencies", amine@400: [ amine@400: ("mono_400Hz", (400,)), # mono amine@400: ("3channel_400-800-1600Hz", (400, 800, 1600)), # multichannel amine@400: ], amine@400: ids=["mono", "multichannel"], amine@400: ) amine@400: def test_WaveAudioSource(file_suffix, frequencies): amine@400: file = "tests/data/test_16KHZ_{}.wav".format(file_suffix) amine@400: audio_source = WaveAudioSource(file) amine@400: audio_source.open() amine@400: data = b"".join(audio_source_read_all_gen(audio_source)) amine@400: audio_source.close() amine@400: mono_channels = [PURE_TONE_DICT[freq] for freq in frequencies] amine@405: dtype = SAMPLE_WIDTH_TO_DTYPE[audio_source.sample_width] amine@405: expected = np.fromiter(_sample_generator(*mono_channels), dtype).tobytes() amine@164: amine@400: assert data == expected amine@164: amine@400: # assert read all data with None amine@400: audio_source = WaveAudioSource(file) amine@400: audio_source.open() amine@400: data_read_all = audio_source.read(None) amine@400: audio_source.close() amine@400: assert data_read_all == expected amine@238: amine@400: # assert read all data with a negative size amine@400: audio_source = WaveAudioSource(file) amine@400: audio_source.open() amine@400: data_read_all = audio_source.read(-10) amine@400: audio_source.close() amine@400: assert data_read_all == expected amine@238: amine@164: amine@400: class TestBufferAudioSource_SR10_SW1_CH1: amine@400: @pytest.fixture(autouse=True) amine@400: def setup_and_teardown(self): amine@164: self.data = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ012345" amine@164: self.audio_source = BufferAudioSource( amine@321: data=self.data, sampling_rate=10, sample_width=1, channels=1 amine@164: ) amine@164: self.audio_source.open() amine@400: yield amine@164: self.audio_source.close() amine@164: amine@164: def test_sr10_sw1_ch1_read_1(self): amine@164: block = self.audio_source.read(1) amine@164: exp = b"A" amine@400: assert block == exp amine@164: amine@164: def test_sr10_sw1_ch1_read_6(self): amine@164: block = self.audio_source.read(6) amine@164: exp = b"ABCDEF" amine@400: assert block == exp amine@164: amine@164: def test_sr10_sw1_ch1_read_multiple(self): amine@164: block = self.audio_source.read(1) amine@164: exp = b"A" amine@400: assert block == exp amine@164: amine@164: block = self.audio_source.read(6) amine@164: exp = b"BCDEFG" amine@400: assert block == exp amine@164: amine@164: block = self.audio_source.read(13) amine@164: exp = b"HIJKLMNOPQRST" amine@400: assert block == exp amine@164: amine@164: block = self.audio_source.read(9999) amine@164: exp = b"UVWXYZ012345" amine@400: assert block == exp amine@164: amine@164: def test_sr10_sw1_ch1_read_all(self): amine@164: block = self.audio_source.read(9999) amine@400: assert block == self.data amine@164: amine@164: block = self.audio_source.read(1) amine@400: assert block is None amine@164: amine@335: def test_sr10_sw1_ch1_sampling_rate(self): amine@335: srate = self.audio_source.sampling_rate amine@400: assert srate == 10 amine@164: amine@335: def test_sr10_sw1_ch1_sample_width(self): amine@335: swidth = self.audio_source.sample_width amine@400: assert swidth == 1 amine@164: amine@335: def test_sr10_sw1_ch1_channels(self): amine@335: channels = self.audio_source.channels amine@400: assert channels == 1 amine@164: amine@400: @pytest.mark.parametrize( amine@400: "block_sizes, expected_sample, expected_second, expected_ms", amine@400: [ amine@400: ([], 0, 0, 0), # empty amine@400: ([0], 0, 0, 0), # zero amine@400: ([5], 5, 0.5, 500), # five amine@400: ([5, 20], 25, 2.5, 2500), # multiple amine@400: ], amine@400: ids=["empty", "zero", "five", "multiple"], amine@166: ) amine@166: def test_position( amine@166: self, block_sizes, expected_sample, expected_second, expected_ms amine@166: ): amine@166: for block_size in block_sizes: amine@166: self.audio_source.read(block_size) amine@166: position = self.audio_source.position amine@400: assert position == expected_sample amine@166: amine@166: position_s = self.audio_source.position_s amine@400: assert position_s == expected_second amine@166: amine@166: position_ms = self.audio_source.position_ms amine@400: assert position_ms == expected_ms amine@166: amine@400: @pytest.mark.parametrize( amine@400: "position, expected_sample, expected_second, expected_ms", amine@400: [ amine@400: (0, 0, 0, 0), # zero amine@400: (1, 1, 0.1, 100), # one amine@400: (10, 10, 1, 1000), # ten amine@400: (-1, 31, 3.1, 3100), # negative_1 amine@400: (-7, 25, 2.5, 2500), # negative_2 amine@400: ], amine@400: ids=["zero", "one", "ten", "negative_1", "negative_2"], amine@166: ) amine@166: def test_position_setter( amine@166: self, position, expected_sample, expected_second, expected_ms amine@166: ): amine@166: self.audio_source.position = position amine@166: amine@166: position = self.audio_source.position amine@400: assert position == expected_sample amine@166: amine@166: position_s = self.audio_source.position_s amine@400: assert position_s == expected_second amine@166: amine@166: position_ms = self.audio_source.position_ms amine@400: assert position_ms == expected_ms amine@166: amine@400: @pytest.mark.parametrize( amine@400: "position_s, expected_sample, expected_second, expected_ms", amine@400: [ amine@400: (0, 0, 0, 0), # zero amine@400: (0.1, 1, 0.1, 100), # one amine@400: (1, 10, 1, 1000), # ten amine@400: (-0.1, 31, 3.1, 3100), # negative_1 amine@400: (-0.7, 25, 2.5, 2500), # negative_2 amine@400: ], amine@400: ids=["zero", "one", "ten", "negative_1", "negative_2"], amine@166: ) amine@166: def test_position_s_setter( amine@166: self, position_s, expected_sample, expected_second, expected_ms amine@166: ): amine@166: self.audio_source.position_s = position_s amine@166: amine@166: position = self.audio_source.position amine@400: assert position == expected_sample amine@166: amine@166: position_s = self.audio_source.position_s amine@400: assert position_s == expected_second amine@166: amine@166: position_ms = self.audio_source.position_ms amine@400: assert position_ms == expected_ms amine@166: amine@400: @pytest.mark.parametrize( amine@400: "position_ms, expected_sample, expected_second, expected_ms", amine@400: [ amine@400: (0, 0, 0, 0), # zero amine@400: (100, 1, 0.1, 100), # one amine@400: (1000, 10, 1, 1000), # ten amine@400: (-100, 31, 3.1, 3100), # negative_1 amine@400: (-700, 25, 2.5, 2500), # negative_2 amine@400: ], amine@400: ids=["zero", "one", "ten", "negative_1", "negative_2"], amine@166: ) amine@166: def test_position_ms_setter( amine@166: self, position_ms, expected_sample, expected_second, expected_ms amine@166: ): amine@166: self.audio_source.position_ms = position_ms amine@166: amine@166: position = self.audio_source.position amine@400: assert position == expected_sample amine@166: amine@166: position_s = self.audio_source.position_s amine@400: assert position_s == expected_second amine@166: amine@166: position_ms = self.audio_source.position_ms amine@400: assert position_ms == expected_ms amine@166: amine@400: @pytest.mark.parametrize( amine@400: "position", amine@400: [ amine@400: 100, # positive amine@400: -100, # negative amine@400: ], amine@400: ids=["positive", "negative"], amine@400: ) amine@166: def test_position_setter_out_of_range(self, position): amine@400: with pytest.raises(IndexError): amine@166: self.audio_source.position = position amine@166: amine@400: @pytest.mark.parametrize( amine@400: "position_s", amine@400: [ amine@400: 100, # positive amine@400: -100, # negative amine@400: ], amine@400: ids=["positive", "negative"], amine@400: ) amine@166: def test_position_s_setter_out_of_range(self, position_s): amine@400: with pytest.raises(IndexError): amine@166: self.audio_source.position_s = position_s amine@166: amine@400: @pytest.mark.parametrize( amine@400: "position_ms", amine@400: [ amine@400: 10000, # positive amine@400: -10000, # negative amine@400: ], amine@400: ids=["positive", "negative"], amine@400: ) amine@166: def test_position_ms_setter_out_of_range(self, position_ms): amine@400: with pytest.raises(IndexError): amine@166: self.audio_source.position_ms = position_ms amine@166: amine@330: def test_sr10_sw1_ch1_initial_position_s_0(self): amine@216: tp = self.audio_source.position_s amine@400: assert tp == 0.0 amine@164: amine@330: def test_sr10_sw1_ch1_position_s_1_after_read(self): amine@330: srate = self.audio_source.sampling_rate amine@164: # read one second amine@164: self.audio_source.read(srate) amine@216: tp = self.audio_source.position_s amine@400: assert tp == 1.0 amine@164: amine@216: def test_sr10_sw1_ch1_position_s_2_5(self): amine@164: # read 2.5 seconds amine@164: self.audio_source.read(25) amine@216: tp = self.audio_source.position_s amine@400: assert tp == 2.5 amine@164: amine@216: def test_sr10_sw1_ch1_position_s_0(self): amine@164: self.audio_source.read(10) amine@216: self.audio_source.position_s = 0 amine@216: tp = self.audio_source.position_s amine@400: assert tp == 0.0 amine@164: amine@216: def test_sr10_sw1_ch1_position_s_1(self): amine@216: self.audio_source.position_s = 1 amine@216: tp = self.audio_source.position_s amine@400: assert tp == 1.0 amine@164: amine@164: def test_sr10_sw1_ch1_rewind(self): amine@164: self.audio_source.read(10) amine@164: self.audio_source.rewind() amine@169: tp = self.audio_source.position amine@400: assert tp == 0 amine@164: amine@164: def test_sr10_sw1_ch1_read_closed(self): amine@164: self.audio_source.close() amine@405: with pytest.raises(AudioIOError): amine@164: self.audio_source.read(1) amine@164: amine@209: amine@400: class TestBufferAudioSource_SR16_SW2_CH1: amine@400: @pytest.fixture(autouse=True) amine@400: def setup_and_teardown(self): amine@164: self.data = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ012345" amine@164: self.audio_source = BufferAudioSource( amine@321: data=self.data, sampling_rate=16, sample_width=2, channels=1 amine@164: ) amine@164: self.audio_source.open() amine@400: yield amine@164: self.audio_source.close() amine@164: amine@164: def test_sr16_sw2_ch1_read_1(self): amine@164: block = self.audio_source.read(1) amine@164: exp = b"AB" amine@400: assert block == exp amine@164: amine@164: def test_sr16_sw2_ch1_read_6(self): amine@164: block = self.audio_source.read(6) amine@164: exp = b"ABCDEFGHIJKL" amine@400: assert block == exp amine@164: amine@164: def test_sr16_sw2_ch1_read_multiple(self): amine@164: block = self.audio_source.read(1) amine@164: exp = b"AB" amine@400: assert block == exp amine@164: amine@164: block = self.audio_source.read(6) amine@164: exp = b"CDEFGHIJKLMN" amine@400: assert block == exp amine@164: amine@164: block = self.audio_source.read(5) amine@164: exp = b"OPQRSTUVWX" amine@400: assert block == exp amine@164: amine@164: block = self.audio_source.read(9999) amine@164: exp = b"YZ012345" amine@400: assert block == exp amine@164: amine@164: def test_sr16_sw2_ch1_read_all(self): amine@164: block = self.audio_source.read(9999) amine@400: assert block == self.data amine@164: amine@164: block = self.audio_source.read(1) amine@400: assert block is None amine@164: amine@335: def test_sr16_sw2_ch1_sampling_rate(self): amine@335: srate = self.audio_source.sampling_rate amine@400: assert srate == 16 amine@164: amine@335: def test_sr16_sw2_ch1_sample_width(self): amine@335: swidth = self.audio_source.sample_width amine@400: assert swidth == 2 amine@164: amine@335: def test_sr16_sw2_ch1_channels(self): amine@400: channels = self.audio_source.channels amine@400: assert channels == 1 amine@164: amine@400: @pytest.mark.parametrize( amine@400: "block_sizes, expected_sample, expected_second, expected_ms", amine@400: [ amine@400: ([], 0, 0, 0), # empty amine@400: ([0], 0, 0, 0), # zero amine@400: ([2], 2, 2 / 16, int(2000 / 16)), # two amine@400: ([11], 11, 11 / 16, int(11 * 1000 / 16)), # eleven amine@400: ([4, 8], 12, 0.75, 750), # multiple amine@400: ], amine@400: ids=["empty", "zero", "two", "eleven", "multiple"], amine@169: ) amine@169: def test_position( amine@169: self, block_sizes, expected_sample, expected_second, expected_ms amine@169: ): amine@169: for block_size in block_sizes: amine@169: self.audio_source.read(block_size) amine@169: position = self.audio_source.position amine@400: assert position == expected_sample amine@169: amine@169: position_s = self.audio_source.position_s amine@400: assert position_s == expected_second amine@169: amine@169: position_ms = self.audio_source.position_ms amine@400: assert position_ms == expected_ms amine@169: amine@216: def test_sr16_sw2_ch1_read_position_0(self): amine@169: self.audio_source.read(10) amine@169: self.audio_source.position = 0 amine@169: pos = self.audio_source.position amine@400: assert pos == 0 amine@164: amine@400: @pytest.mark.parametrize( amine@400: "position, expected_sample, expected_second, expected_ms", amine@400: [ amine@400: (0, 0, 0, 0), # zero amine@400: (1, 1, 1 / 16, int(1000 / 16)), # one amine@400: (10, 10, 10 / 16, int(10000 / 16)), # ten amine@400: (-1, 15, 15 / 16, int(15000 / 16)), # negative_1 amine@400: (-7, 9, 9 / 16, int(9000 / 16)), # negative_2 amine@400: ], amine@400: ids=["zero", "one", "ten", "negative_1", "negative_2"], amine@169: ) amine@169: def test_position_setter( amine@169: self, position, expected_sample, expected_second, expected_ms amine@169: ): amine@169: self.audio_source.position = position amine@169: amine@169: position = self.audio_source.position amine@400: assert position == expected_sample amine@164: amine@169: position_s = self.audio_source.position_s amine@400: assert position_s == expected_second amine@164: amine@169: position_ms = self.audio_source.position_ms amine@400: assert position_ms == expected_ms amine@164: amine@400: @pytest.mark.parametrize( amine@400: "position_s, expected_sample, expected_second, expected_ms", amine@400: [ amine@400: (0, 0, 0, 0), # zero amine@400: (0.1, 1, 1 / 16, int(1000 / 16)), # one amine@400: (1 / 8, 2, 1 / 8, int(1 / 8 * 1000)), # two amine@400: (0.75, 12, 0.75, 750), # twelve amine@400: (-0.1, 15, 15 / 16, int(15000 / 16)), # negative_1 amine@400: (-0.7, 5, 5 / 16, int(5000 / 16)), # negative_2 amine@400: ], amine@400: ids=["zero", "one", "two", "twelve", "negative_1", "negative_2"], amine@169: ) amine@169: def test_position_s_setter( amine@169: self, position_s, expected_sample, expected_second, expected_ms amine@169: ): amine@169: self.audio_source.position_s = position_s amine@169: amine@169: position = self.audio_source.position amine@400: assert position == expected_sample amine@164: amine@169: position_s = self.audio_source.position_s amine@400: assert position_s == expected_second amine@164: amine@169: position_ms = self.audio_source.position_ms amine@400: assert position_ms == expected_ms amine@164: amine@400: @pytest.mark.parametrize( amine@400: "position_ms, expected_sample, expected_second, expected_ms", amine@400: [ amine@400: (0, 0, 0, 0), # zero amine@400: (100, 1, 1 / 16, int(1000 / 16)), # one amine@400: (1000, 16, 1, 1000), # ten amine@400: (-100, 15, 15 / 16, int(15 * 1000 / 16)), # negative_1 amine@400: (-500, 8, 0.5, 500), # negative_2 amine@400: (-700, 5, 5 / 16, int(5 * 1000 / 16)), # negative_3 amine@400: ], amine@400: ids=["zero", "one", "ten", "negative_1", "negative_2", "negative_3"], amine@169: ) amine@169: def test_position_ms_setter( amine@169: self, position_ms, expected_sample, expected_second, expected_ms amine@169: ): amine@169: self.audio_source.position_ms = position_ms amine@169: amine@169: position = self.audio_source.position amine@400: assert position == expected_sample amine@164: amine@169: position_s = self.audio_source.position_s amine@400: assert position_s == expected_second amine@164: amine@169: position_ms = self.audio_source.position_ms amine@400: assert position_ms == expected_ms amine@164: amine@164: def test_sr16_sw2_ch1_rewind(self): amine@164: self.audio_source.read(10) amine@164: self.audio_source.rewind() amine@216: tp = self.audio_source.position amine@400: assert tp == 0 amine@164: amine@164: amine@400: class TestBufferAudioSource_SR11_SW4_CH1: amine@400: @pytest.fixture(autouse=True) amine@400: def setup_and_teardown(self): amine@164: self.data = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefgh" amine@164: self.audio_source = BufferAudioSource( amine@321: data=self.data, sampling_rate=11, sample_width=4, channels=1 amine@164: ) amine@164: self.audio_source.open() amine@400: yield amine@164: self.audio_source.close() amine@164: amine@164: def test_sr11_sw4_ch1_read_1(self): amine@164: block = self.audio_source.read(1) amine@164: exp = b"ABCD" amine@400: assert block == exp amine@164: amine@164: def test_sr11_sw4_ch1_read_6(self): amine@164: block = self.audio_source.read(6) amine@164: exp = b"ABCDEFGHIJKLMNOPQRSTUVWX" amine@400: assert block == exp amine@164: amine@164: def test_sr11_sw4_ch1_read_multiple(self): amine@164: block = self.audio_source.read(1) amine@164: exp = b"ABCD" amine@400: assert block == exp amine@164: amine@164: block = self.audio_source.read(6) amine@164: exp = b"EFGHIJKLMNOPQRSTUVWXYZ01" amine@400: assert block == exp amine@164: amine@164: block = self.audio_source.read(3) amine@164: exp = b"23456789abcd" amine@400: assert block == exp amine@164: amine@164: block = self.audio_source.read(9999) amine@164: exp = b"efgh" amine@400: assert block == exp amine@164: amine@164: def test_sr11_sw4_ch1_read_all(self): amine@164: block = self.audio_source.read(9999) amine@400: assert block == self.data amine@164: amine@164: block = self.audio_source.read(1) amine@400: assert block is None amine@164: amine@335: def test_sr11_sw4_ch1_sampling_rate(self): amine@335: srate = self.audio_source.sampling_rate amine@400: assert srate == 11 amine@164: amine@335: def test_sr11_sw4_ch1_sample_width(self): amine@335: swidth = self.audio_source.sample_width amine@400: assert swidth == 4 amine@164: amine@335: def test_sr11_sw4_ch1_channels(self): amine@335: channels = self.audio_source.channels amine@400: assert channels == 1 amine@164: amine@330: def test_sr11_sw4_ch1_intial_position_0(self): amine@216: pos = self.audio_source.position amine@400: assert pos == 0 amine@164: amine@216: def test_sr11_sw4_ch1_position_5(self): amine@164: self.audio_source.read(5) amine@216: pos = self.audio_source.position amine@400: assert pos == 5 amine@164: amine@216: def test_sr11_sw4_ch1_position_9(self): amine@164: self.audio_source.read(5) amine@164: self.audio_source.read(4) amine@216: pos = self.audio_source.position amine@400: assert pos == 9 amine@164: amine@216: def test_sr11_sw4_ch1_position_0(self): amine@164: self.audio_source.read(10) amine@216: self.audio_source.position = 0 amine@216: pos = self.audio_source.position amine@400: assert pos == 0 amine@164: amine@216: def test_sr11_sw4_ch1_position_10(self): amine@216: self.audio_source.position = 10 amine@216: pos = self.audio_source.position amine@400: assert pos == 10 amine@164: amine@330: def test_sr11_sw4_ch1_initial_position_s_0(self): amine@216: tp = self.audio_source.position_s amine@400: assert tp == 0.0 amine@164: amine@330: def test_sr11_sw4_ch1_position_s_1_after_read(self): amine@330: srate = self.audio_source.sampling_rate amine@164: # read one second amine@164: self.audio_source.read(srate) amine@216: tp = self.audio_source.position_s amine@400: assert tp == 1.0 amine@164: amine@216: def test_sr11_sw4_ch1_position_s_0_63(self): amine@164: # read 2.5 seconds amine@164: self.audio_source.read(7) amine@216: tp = self.audio_source.position_s amine@400: assert tp, pytest.approx(0.636363636364) amine@164: amine@216: def test_sr11_sw4_ch1_position_s_0(self): amine@164: self.audio_source.read(10) amine@216: self.audio_source.position_s = 0 amine@216: tp = self.audio_source.position_s amine@400: assert tp == 0.0 amine@164: amine@216: def test_sr11_sw4_ch1_position_s_1(self): amine@216: self.audio_source.position_s = 1 amine@216: tp = self.audio_source.position_s amine@400: assert tp == 1.0 amine@164: amine@164: def test_sr11_sw4_ch1_rewind(self): amine@164: self.audio_source.read(10) amine@164: self.audio_source.rewind() amine@169: tp = self.audio_source.position amine@400: assert tp == 0 amine@164: amine@164: amine@400: class TestBufferAudioSourceCreationException: amine@164: def test_wrong_sample_width_value(self): amine@400: with pytest.raises(AudioParameterError) as audio_param_err: amine@164: _ = BufferAudioSource( amine@321: data=b"ABCDEFGHI", sampling_rate=9, sample_width=3, channels=1 amine@164: ) amine@400: assert ( amine@400: str(audio_param_err.value) amine@400: == "Sample width must be one of: 1, 2 or 4 (bytes)" amine@164: ) amine@164: amine@164: def test_wrong_data_buffer_size(self): amine@400: with pytest.raises(AudioParameterError) as audio_param_err: amine@164: _ = BufferAudioSource( amine@321: data=b"ABCDEFGHI", sampling_rate=8, sample_width=2, channels=1 amine@164: ) amine@405: msg = "The length of audio data must be an integer multiple of " amine@405: msg += "`sample_width * channels`" amine@405: assert str(audio_param_err.value) == msg amine@164: amine@164: amine@400: class TestAudioSourceProperties: amine@164: def test_read_properties(self): amine@164: data = b"" amine@164: sampling_rate = 8000 amine@164: sample_width = 2 amine@164: channels = 1 amine@164: a_source = BufferAudioSource( amine@164: data, sampling_rate, sample_width, channels amine@164: ) amine@164: amine@400: assert a_source.sampling_rate == sampling_rate amine@400: assert a_source.sample_width == sample_width amine@400: assert a_source.channels == channels amine@164: amine@164: def test_set_readonly_properties_exception(self): amine@164: data = b"" amine@164: sampling_rate = 8000 amine@164: sample_width = 2 amine@164: channels = 1 amine@164: a_source = BufferAudioSource( amine@164: data, sampling_rate, sample_width, channels amine@164: ) amine@164: amine@400: with pytest.raises(AttributeError): amine@164: a_source.sampling_rate = 16000 amine@405: amine@405: with pytest.raises(AttributeError): amine@164: a_source.sample_width = 1 amine@405: amine@405: with pytest.raises(AttributeError): amine@164: a_source.channels = 2 amine@164: amine@164: amine@400: class TestAudioSourceShortProperties: amine@164: def test_read_short_properties(self): amine@164: data = b"" amine@164: sampling_rate = 8000 amine@164: sample_width = 2 amine@164: channels = 1 amine@164: a_source = BufferAudioSource( amine@164: data, sampling_rate, sample_width, channels amine@164: ) amine@164: amine@400: assert a_source.sr == sampling_rate amine@400: assert a_source.sw == sample_width amine@400: assert a_source.ch == channels amine@164: amine@164: def test_set_readonly_short_properties_exception(self): amine@164: data = b"" amine@164: sampling_rate = 8000 amine@164: sample_width = 2 amine@164: channels = 1 amine@164: a_source = BufferAudioSource( amine@164: data, sampling_rate, sample_width, channels amine@164: ) amine@164: amine@400: with pytest.raises(AttributeError): amine@164: a_source.sr = 16000 amine@405: amine@405: with pytest.raises(AttributeError): amine@164: a_source.sw = 1 amine@405: amine@405: with pytest.raises(AttributeError): amine@164: a_source.ch = 2