amine@157
|
1 import math
|
amine@357
|
2 from array import array as array_
|
amine@403
|
3 from unittest.mock import patch
|
amine@403
|
4
|
amine@405
|
5 import numpy as np
|
amine@403
|
6 import pytest
|
amine@403
|
7
|
amine@405
|
8 from auditok import signal
|
amine@345
|
9 from auditok.exceptions import TimeFormatError
|
amine@403
|
10 from auditok.util import (
|
amine@403
|
11 AudioEnergyValidator,
|
amine@403
|
12 make_channel_selector,
|
amine@403
|
13 make_duration_formatter,
|
amine@403
|
14 )
|
amine@157
|
15
|
amine@157
|
16
|
amine@405
|
17 @pytest.fixture
|
amine@405
|
18 def setup_data():
|
amine@405
|
19 return b"012345679ABC"
|
amine@157
|
20
|
amine@157
|
21
|
amine@405
|
22 @pytest.mark.parametrize(
|
amine@405
|
23 "fmt, duration, expected",
|
amine@405
|
24 [
|
amine@405
|
25 ("%S", 5400, "5400.000"), # only_seconds
|
amine@405
|
26 ("%I", 5400, "5400000"), # only_millis
|
amine@405
|
27 ("%h:%m:%s.%i", 3725.365, "01:02:05.365"), # full
|
amine@405
|
28 ("%h:%m:%s.%i", 1925.075, "00:32:05.075"), # full_zero_hours
|
amine@405
|
29 ("%h:%m:%s.%i", 3659.075, "01:00:59.075"), # full_zero_minutes
|
amine@405
|
30 ("%h:%m:%s.%i", 3720.075, "01:02:00.075"), # full_zero_seconds
|
amine@405
|
31 ("%h:%m:%s.%i", 3725, "01:02:05.000"), # full_zero_millis
|
amine@405
|
32 (
|
amine@405
|
33 "%h %h:%m:%s.%i %s",
|
amine@405
|
34 3725.365,
|
amine@405
|
35 "01 01:02:05.365 05",
|
amine@405
|
36 ), # duplicate_directive
|
amine@405
|
37 ("%h:%m:%s", 3725, "01:02:05"), # no_millis
|
amine@405
|
38 ("%h:%m", 3725, "01:02"), # no_seconds
|
amine@405
|
39 ("%h", 3725, "01"), # no_minutes
|
amine@405
|
40 ("%m:%s.%i", 3725, "02:05.000"), # no_hours
|
amine@405
|
41 ],
|
amine@405
|
42 ids=[
|
amine@405
|
43 "only_seconds",
|
amine@405
|
44 "only_millis",
|
amine@405
|
45 "full",
|
amine@405
|
46 "full_zero_hours",
|
amine@405
|
47 "full_zero_minutes",
|
amine@405
|
48 "full_zero_seconds",
|
amine@405
|
49 "full_zero_millis",
|
amine@405
|
50 "duplicate_directive",
|
amine@405
|
51 "no_millis",
|
amine@405
|
52 "no_seconds",
|
amine@405
|
53 "no_minutes",
|
amine@405
|
54 "no_hours",
|
amine@405
|
55 ],
|
amine@405
|
56 )
|
amine@405
|
57 def test_make_duration_formatter(fmt, duration, expected):
|
amine@405
|
58 formatter = make_duration_formatter(fmt)
|
amine@405
|
59 result = formatter(duration)
|
amine@405
|
60 assert result == expected
|
amine@405
|
61
|
amine@405
|
62
|
amine@405
|
63 @pytest.mark.parametrize(
|
amine@405
|
64 "fmt",
|
amine@405
|
65 [
|
amine@405
|
66 "%S %S", # duplicate_only_seconds
|
amine@405
|
67 "%I %I", # duplicate_only_millis
|
amine@405
|
68 "%x", # unknown_directive
|
amine@405
|
69 ],
|
amine@405
|
70 ids=[
|
amine@405
|
71 "duplicate_only_seconds",
|
amine@405
|
72 "duplicate_only_millis",
|
amine@405
|
73 "unknown_directive",
|
amine@405
|
74 ],
|
amine@405
|
75 )
|
amine@405
|
76 def test_make_duration_formatter_error(fmt):
|
amine@405
|
77 with pytest.raises(TimeFormatError):
|
amine@405
|
78 make_duration_formatter(fmt)
|
amine@405
|
79
|
amine@405
|
80
|
amine@405
|
81 @pytest.mark.parametrize(
|
amine@405
|
82 "sample_width, channels, selected, expected",
|
amine@405
|
83 [
|
amine@405
|
84 (
|
amine@405
|
85 1,
|
amine@405
|
86 1,
|
amine@405
|
87 0,
|
amine@405
|
88 [48, 49, 50, 51, 52, 53, 54, 55, 57, 65, 66, 67],
|
amine@405
|
89 ), # int8_1channel_select_0
|
amine@405
|
90 (1, 2, 0, [48, 50, 52, 54, 57, 66]), # int8_2channel_select_0
|
amine@405
|
91 (1, 3, 0, [48, 51, 54, 65]), # int8_3channel_select_0
|
amine@405
|
92 (1, 3, 1, [49, 52, 55, 66]), # int8_3channel_select_1
|
amine@405
|
93 (1, 3, 2, [50, 53, 57, 67]), # int8_3channel_select_2
|
amine@405
|
94 (1, 4, 0, [48, 52, 57]), # int8_4channel_select_0
|
amine@405
|
95 (
|
amine@405
|
96 2,
|
amine@405
|
97 1,
|
amine@405
|
98 0,
|
amine@405
|
99 [12592, 13106, 13620, 14134, 16697, 17218],
|
amine@405
|
100 ), # int16_1channel_select_0
|
amine@405
|
101 (2, 2, 0, [12592, 13620, 16697]), # int16_2channel_select_0
|
amine@405
|
102 (2, 2, 1, [13106, 14134, 17218]), # int16_2channel_select_1
|
amine@405
|
103 (2, 3, 0, [12592, 14134]), # int16_3channel_select_0
|
amine@405
|
104 (2, 3, 1, [13106, 16697]), # int16_3channel_select_1
|
amine@405
|
105 (2, 3, 2, [13620, 17218]), # int16_3channel_select_2
|
amine@405
|
106 (
|
amine@405
|
107 4,
|
amine@405
|
108 1,
|
amine@405
|
109 0,
|
amine@405
|
110 [858927408, 926299444, 1128415545],
|
amine@405
|
111 ), # int32_1channel_select_0
|
amine@405
|
112 (4, 3, 0, [858927408]), # int32_3channel_select_0
|
amine@405
|
113 (4, 3, 1, [926299444]), # int32_3channel_select_1
|
amine@405
|
114 (4, 3, 2, [1128415545]), # int32_3channel_select_2
|
amine@405
|
115 ],
|
amine@405
|
116 ids=[
|
amine@405
|
117 "int8_1channel_select_0",
|
amine@405
|
118 "int8_2channel_select_0",
|
amine@405
|
119 "int8_3channel_select_0",
|
amine@405
|
120 "int8_3channel_select_1",
|
amine@405
|
121 "int8_3channel_select_2",
|
amine@405
|
122 "int8_4channel_select_0",
|
amine@405
|
123 "int16_1channel_select_0",
|
amine@405
|
124 "int16_2channel_select_0",
|
amine@405
|
125 "int16_2channel_select_1",
|
amine@405
|
126 "int16_3channel_select_0",
|
amine@405
|
127 "int16_3channel_select_1",
|
amine@405
|
128 "int16_3channel_select_2",
|
amine@405
|
129 "int32_1channel_select_0",
|
amine@405
|
130 "int32_3channel_select_0",
|
amine@405
|
131 "int32_3channel_select_1",
|
amine@405
|
132 "int32_3channel_select_2",
|
amine@405
|
133 ],
|
amine@405
|
134 )
|
amine@405
|
135 def test_make_channel_selector_one_channel(
|
amine@405
|
136 setup_data, sample_width, channels, selected, expected
|
amine@157
|
137 ):
|
amine@157
|
138
|
amine@405
|
139 selector = make_channel_selector(sample_width, channels, selected)
|
amine@405
|
140 result = selector(setup_data)
|
amine@157
|
141
|
amine@405
|
142 dtype = signal.SAMPLE_WIDTH_TO_DTYPE[sample_width]
|
amine@405
|
143 expected = np.array(expected).astype(dtype)
|
amine@405
|
144 assert (result == expected).all()
|
amine@405
|
145
|
amine@405
|
146
|
amine@405
|
147 @pytest.mark.parametrize(
|
amine@405
|
148 "sample_width, channels, selected, expected",
|
amine@405
|
149 [
|
amine@405
|
150 (
|
amine@405
|
151 1,
|
amine@405
|
152 1,
|
amine@405
|
153 "avg",
|
amine@405
|
154 [48, 49, 50, 51, 52, 53, 54, 55, 57, 65, 66, 67],
|
amine@405
|
155 ), # int8_1channel
|
amine@405
|
156 (1, 2, "mix", [48.5, 50.5, 52.5, 54.5, 61, 66.5]), # int8_2channel
|
amine@405
|
157 (1, 4, "average", [49.5, 53.5, 63.75]), # int8_4channel
|
amine@405
|
158 (
|
amine@405
|
159 2,
|
amine@405
|
160 1,
|
amine@405
|
161 "mix",
|
amine@405
|
162 [12592, 13106, 13620, 14134, 16697, 17218],
|
amine@405
|
163 ), # int16_1channel
|
amine@405
|
164 (2, 2, "avg", [12849, 13877, 16957.5]), # int16_2channel
|
amine@405
|
165 (4, 3, "average", [971214132.33]), # int32_3channel
|
amine@405
|
166 ],
|
amine@405
|
167 ids=[
|
amine@405
|
168 "int8_1channel",
|
amine@405
|
169 "int8_2channel",
|
amine@405
|
170 "int8_4channel",
|
amine@405
|
171 "int16_1channel",
|
amine@405
|
172 "int16_2channel",
|
amine@405
|
173 "int32_3channel",
|
amine@405
|
174 ],
|
amine@157
|
175 )
|
amine@405
|
176 def test_make_channel_selector_average(
|
amine@405
|
177 setup_data, sample_width, channels, selected, expected
|
amine@405
|
178 ):
|
amine@317
|
179
|
amine@405
|
180 selector = make_channel_selector(sample_width, channels, selected)
|
amine@405
|
181 result = selector(setup_data).round(2)
|
amine@405
|
182 assert (result == expected).all()
|
amine@317
|
183
|
amine@357
|
184
|
amine@405
|
185 @pytest.mark.parametrize(
|
amine@405
|
186 "sample_width, channels, selected, expected",
|
amine@405
|
187 [
|
amine@405
|
188 (
|
amine@405
|
189 1,
|
amine@405
|
190 1,
|
amine@405
|
191 "any",
|
amine@405
|
192 [[48, 49, 50, 51, 52, 53, 54, 55, 57, 65, 66, 67]],
|
amine@405
|
193 ), # int8_1channel
|
amine@405
|
194 (
|
amine@405
|
195 1,
|
amine@405
|
196 2,
|
amine@405
|
197 None,
|
amine@405
|
198 [[48, 50, 52, 54, 57, 66], [49, 51, 53, 55, 65, 67]],
|
amine@405
|
199 ), # int8_2channel
|
amine@405
|
200 (
|
amine@405
|
201 1,
|
amine@405
|
202 4,
|
amine@405
|
203 "any",
|
amine@405
|
204 [[48, 52, 57], [49, 53, 65], [50, 54, 66], [51, 55, 67]],
|
amine@405
|
205 ), # int8_4channel
|
amine@405
|
206 (
|
amine@405
|
207 2,
|
amine@405
|
208 2,
|
amine@405
|
209 None,
|
amine@405
|
210 [[12592, 13620, 16697], [13106, 14134, 17218]],
|
amine@405
|
211 ), # int16_2channel
|
amine@405
|
212 (
|
amine@405
|
213 4,
|
amine@405
|
214 3,
|
amine@405
|
215 "any",
|
amine@405
|
216 [[858927408], [926299444], [1128415545]],
|
amine@405
|
217 ), # int32_3channel
|
amine@405
|
218 ],
|
amine@405
|
219 ids=[
|
amine@405
|
220 "int8_1channel",
|
amine@405
|
221 "int8_2channel",
|
amine@405
|
222 "int8_4channel",
|
amine@405
|
223 "int16_2channel",
|
amine@405
|
224 "int32_3channel",
|
amine@405
|
225 ],
|
amine@405
|
226 )
|
amine@405
|
227 def test_make_channel_selector_any(
|
amine@405
|
228 setup_data, sample_width, channels, selected, expected
|
amine@405
|
229 ):
|
amine@345
|
230
|
amine@405
|
231 # Use signal functions with numpy implementation
|
amine@405
|
232 selector = make_channel_selector(sample_width, channels, selected)
|
amine@405
|
233 result = selector(setup_data)
|
amine@405
|
234 assert (result == expected).all()
|
amine@357
|
235
|
amine@345
|
236
|
amine@400
|
237 class TestAudioEnergyValidator:
|
amine@400
|
238 @pytest.mark.parametrize(
|
amine@400
|
239 "data, channels, use_channel, expected",
|
amine@400
|
240 [
|
amine@400
|
241 ([350, 400], 1, None, True), # mono_valid_uc_None
|
amine@400
|
242 ([350, 400], 1, "any", True), # mono_valid_uc_any
|
amine@400
|
243 ([350, 400], 1, 0, True), # mono_valid_uc_0
|
amine@400
|
244 ([350, 400], 1, "mix", True), # mono_valid_uc_mix
|
amine@400
|
245 ([300, 300], 1, None, False), # mono_invalid_uc_None
|
amine@400
|
246 ([300, 400, 350, 300], 2, None, True), # stereo_valid_uc_None
|
amine@400
|
247 ([300, 400, 350, 300], 2, "any", True), # stereo_valid_uc_any
|
amine@400
|
248 ([300, 400, 350, 300], 2, "mix", True), # stereo_valid_uc_mix
|
amine@400
|
249 ([300, 400, 350, 300], 2, "avg", True), # stereo_valid_uc_avg
|
amine@400
|
250 (
|
amine@400
|
251 [300, 400, 300, 300],
|
amine@400
|
252 2,
|
amine@400
|
253 "average",
|
amine@400
|
254 True,
|
amine@400
|
255 ), # stereo_valid_uc_average
|
amine@400
|
256 (
|
amine@400
|
257 [634, 0, 634, 0],
|
amine@400
|
258 2,
|
amine@400
|
259 "mix",
|
amine@400
|
260 True,
|
amine@400
|
261 ), # stereo_valid_uc_mix_with_null_channel
|
amine@400
|
262 ([320, 100, 320, 100], 2, 0, True), # stereo_valid_uc_0
|
amine@400
|
263 ([100, 320, 100, 320], 2, 1, True), # stereo_valid_uc_1
|
amine@400
|
264 ([280, 100, 280, 100], 2, None, False), # stereo_invalid_uc_None
|
amine@400
|
265 ([280, 100, 280, 100], 2, "any", False), # stereo_invalid_uc_any
|
amine@400
|
266 ([400, 200, 400, 200], 2, "mix", False), # stereo_invalid_uc_mix
|
amine@400
|
267 ([300, 400, 300, 400], 2, 0, False), # stereo_invalid_uc_0
|
amine@400
|
268 ([400, 300, 400, 300], 2, 1, False), # stereo_invalid_uc_1
|
amine@400
|
269 ([0, 0, 0, 0], 2, None, False), # zeros
|
amine@400
|
270 ],
|
amine@400
|
271 ids=[
|
amine@400
|
272 "mono_valid_uc_None",
|
amine@400
|
273 "mono_valid_uc_any",
|
amine@400
|
274 "mono_valid_uc_0",
|
amine@400
|
275 "mono_valid_uc_mix",
|
amine@400
|
276 "mono_invalid_uc_None",
|
amine@400
|
277 "stereo_valid_uc_None",
|
amine@400
|
278 "stereo_valid_uc_any",
|
amine@400
|
279 "stereo_valid_uc_mix",
|
amine@400
|
280 "stereo_valid_uc_avg",
|
amine@400
|
281 "stereo_valid_uc_average",
|
amine@400
|
282 "stereo_valid_uc_mix_with_null_channel",
|
amine@400
|
283 "stereo_valid_uc_0",
|
amine@400
|
284 "stereo_valid_uc_1",
|
amine@400
|
285 "stereo_invalid_uc_None",
|
amine@400
|
286 "stereo_invalid_uc_any",
|
amine@400
|
287 "stereo_invalid_uc_mix",
|
amine@400
|
288 "stereo_invalid_uc_0",
|
amine@400
|
289 "stereo_invalid_uc_1",
|
amine@400
|
290 "zeros",
|
amine@400
|
291 ],
|
amine@317
|
292 )
|
amine@317
|
293 def test_audio_energy_validator(
|
amine@317
|
294 self, data, channels, use_channel, expected
|
amine@317
|
295 ):
|
amine@317
|
296
|
amine@357
|
297 data = array_("h", data)
|
amine@317
|
298 sample_width = 2
|
amine@317
|
299 energy_threshold = 50
|
amine@317
|
300 validator = AudioEnergyValidator(
|
amine@317
|
301 energy_threshold, sample_width, channels, use_channel
|
amine@317
|
302 )
|
amine@317
|
303
|
amine@317
|
304 if expected:
|
amine@400
|
305 assert validator.is_valid(data)
|
amine@317
|
306 else:
|
amine@400
|
307 assert not validator.is_valid(data)
|