annotate tests/test_util.py @ 455:7dae98b84cdd tip master

Merge branch 'master' of https://github.com/amsehili/auditok
author www-data <www-data@c4dm-xenserv-virt2.eecs.qmul.ac.uk>
date Tue, 03 Dec 2024 09:18:01 +0000
parents f56b4d8adfb8
children
rev   line source
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)