annotate tests/test_core.py @ 187:949678a8cf25

Add save method to AudioRegion
author Amine Sehili <amine.sehili@gmail.com>
date Fri, 05 Apr 2019 20:07:50 +0100
parents ceebd8e331c4
children 94d2f7560a8e
rev   line source
amine@86 1 import unittest
amine@88 2 from random import random
amine@86 3 from genty import genty, genty_dataset
amine@97 4 from auditok import AudioRegion, AudioParameterError
amine@86 5
amine@86 6
amine@88 7 def _make_random_length_regions(
amine@88 8 byte_seq, sampling_rate, sample_width, channels
amine@88 9 ):
amine@88 10 regions = []
amine@88 11 for b in byte_seq:
amine@88 12 duration = round(random() * 10, 6)
amine@95 13 data = b * int(duration * sampling_rate) * sample_width * channels
amine@88 14 start = round(random() * 13, 3)
amine@88 15 region = AudioRegion(
amine@88 16 data, start, sampling_rate, sample_width, channels
amine@88 17 )
amine@88 18 regions.append(region)
amine@88 19 return regions
amine@88 20
amine@88 21
amine@86 22 @genty
amine@86 23 class TestAudioRegion(unittest.TestCase):
amine@86 24 @genty_dataset(
amine@86 25 simple=(b"\0" * 8000, 0, 8000, 1, 1, 1, 1, 1000),
amine@86 26 one_ms_less_than_1_sec=(
amine@86 27 b"\0" * 7992,
amine@86 28 0,
amine@86 29 8000,
amine@86 30 1,
amine@86 31 1,
amine@86 32 0.999,
amine@86 33 0.999,
amine@86 34 999,
amine@86 35 ),
amine@86 36 tree_quarter_ms_less_than_1_sec=(
amine@86 37 b"\0" * 7994,
amine@86 38 0,
amine@86 39 8000,
amine@86 40 1,
amine@86 41 1,
amine@86 42 0.99925,
amine@86 43 0.99925,
amine@86 44 999,
amine@86 45 ),
amine@86 46 half_ms_less_than_1_sec=(
amine@86 47 b"\0" * 7996,
amine@86 48 0,
amine@86 49 8000,
amine@86 50 1,
amine@86 51 1,
amine@86 52 0.9995,
amine@86 53 0.9995,
amine@86 54 1000,
amine@86 55 ),
amine@86 56 quarter_ms_less_than_1_sec=(
amine@86 57 b"\0" * 7998,
amine@86 58 0,
amine@86 59 8000,
amine@86 60 1,
amine@86 61 1,
amine@86 62 0.99975,
amine@86 63 0.99975,
amine@86 64 1000,
amine@86 65 ),
amine@86 66 simple_sample_width_2=(b"\0" * 8000 * 2, 0, 8000, 2, 1, 1, 1, 1000),
amine@86 67 simple_stereo=(b"\0" * 8000 * 2, 0, 8000, 1, 2, 1, 1, 1000),
amine@86 68 simple_multichannel=(b"\0" * 8000 * 5, 0, 8000, 1, 5, 1, 1, 1000),
amine@86 69 simple_sample_width_2_multichannel=(
amine@86 70 b"\0" * 8000 * 2 * 5,
amine@86 71 0,
amine@86 72 8000,
amine@86 73 2,
amine@86 74 5,
amine@86 75 1,
amine@86 76 1,
amine@86 77 1000,
amine@86 78 ),
amine@86 79 one_ms_less_than_1s_sw_2_multichannel=(
amine@86 80 b"\0" * 7992 * 2 * 5,
amine@86 81 0,
amine@86 82 8000,
amine@86 83 2,
amine@86 84 5,
amine@86 85 0.999,
amine@86 86 0.999,
amine@86 87 999,
amine@86 88 ),
amine@86 89 tree_qrt_ms_lt_1_s_sw_2_multichannel=(
amine@86 90 b"\0" * 7994 * 2 * 5,
amine@86 91 0,
amine@86 92 8000,
amine@86 93 2,
amine@86 94 5,
amine@86 95 0.99925,
amine@86 96 0.99925,
amine@86 97 999,
amine@86 98 ),
amine@86 99 half_ms_lt_1s_sw_2_multichannel=(
amine@86 100 b"\0" * 7996 * 2 * 5,
amine@86 101 0,
amine@86 102 8000,
amine@86 103 2,
amine@86 104 5,
amine@86 105 0.9995,
amine@86 106 0.9995,
amine@86 107 1000,
amine@86 108 ),
amine@86 109 quarter_ms_lt_1s_sw_2_multichannel=(
amine@86 110 b"\0" * 7998 * 2 * 5,
amine@86 111 0,
amine@86 112 8000,
amine@86 113 2,
amine@86 114 5,
amine@86 115 0.99975,
amine@86 116 0.99975,
amine@86 117 1000,
amine@86 118 ),
amine@86 119 arbitrary_length_1=(
amine@86 120 b"\0" * int(8000 * 1.33),
amine@86 121 2.7,
amine@86 122 8000,
amine@86 123 1,
amine@86 124 1,
amine@86 125 4.03,
amine@86 126 1.33,
amine@86 127 1330,
amine@86 128 ),
amine@86 129 arbitrary_length_2=(
amine@86 130 b"\0" * int(8000 * 0.476),
amine@86 131 11.568,
amine@86 132 8000,
amine@86 133 1,
amine@86 134 1,
amine@86 135 12.044,
amine@86 136 0.476,
amine@86 137 476,
amine@86 138 ),
amine@86 139 arbitrary_length_sw_2_multichannel=(
amine@86 140 b"\0" * int(8000 * 1.711) * 2 * 3,
amine@86 141 9.415,
amine@86 142 8000,
amine@86 143 2,
amine@86 144 3,
amine@86 145 11.126,
amine@86 146 1.711,
amine@86 147 1711,
amine@86 148 ),
amine@86 149 arbitrary_samplig_rate=(
amine@86 150 b"\0" * int(3172 * 1.318),
amine@86 151 17.236,
amine@86 152 3172,
amine@86 153 1,
amine@86 154 1,
amine@86 155 17.236 + int(3172 * 1.318) / 3172,
amine@86 156 int(3172 * 1.318) / 3172,
amine@86 157 1318,
amine@86 158 ),
amine@86 159 arbitrary_sr_sw_2_multichannel=(
amine@86 160 b"\0" * int(11317 * 0.716) * 2 * 3,
amine@86 161 18.811,
amine@86 162 11317,
amine@86 163 2,
amine@86 164 3,
amine@86 165 18.811 + int(11317 * 0.716) / 11317,
amine@86 166 int(11317 * 0.716) / 11317,
amine@86 167 716,
amine@86 168 ),
amine@86 169 )
amine@86 170 def test_creation(
amine@86 171 self,
amine@86 172 data,
amine@86 173 start,
amine@86 174 sampling_rate,
amine@86 175 sample_width,
amine@86 176 channels,
amine@86 177 expected_end,
amine@86 178 expected_duration_s,
amine@86 179 expected_duration_ms,
amine@86 180 ):
amine@86 181 region = AudioRegion(
amine@86 182 data, start, sampling_rate, sample_width, channels
amine@86 183 )
amine@86 184 self.assertEqual(region.sampling_rate, sampling_rate)
amine@86 185 self.assertEqual(region.sr, sampling_rate)
amine@86 186 self.assertEqual(region.sample_width, sample_width)
amine@86 187 self.assertEqual(region.sw, sample_width)
amine@86 188 self.assertEqual(region.channels, channels)
amine@86 189 self.assertEqual(region.ch, channels)
amine@86 190 self.assertEqual(region.start, start)
amine@86 191 self.assertEqual(region.end, expected_end)
amine@86 192 self.assertEqual(region.duration, expected_duration_s)
amine@86 193 self.assertEqual(len(region), expected_duration_ms)
amine@86 194 self.assertEqual(bytes(region), data)
amine@88 195
amine@97 196 def test_creation_invalid_data_exception(self):
amine@97 197 with self.assertRaises(AudioParameterError) as audio_param_err:
amine@97 198 _ = AudioRegion(
amine@97 199 data=b"ABCDEFGHI",
amine@97 200 start=0,
amine@97 201 sampling_rate=8,
amine@97 202 sample_width=2,
amine@97 203 channels=1,
amine@97 204 )
amine@97 205 self.assertEqual(
amine@97 206 "The length of audio data must be an integer "
amine@97 207 "multiple of `sample_width * channels`",
amine@97 208 str(audio_param_err.exception),
amine@97 209 )
amine@97 210
amine@88 211 @genty_dataset(
amine@88 212 simple=(8000, 1, 1),
amine@88 213 stereo_sw_2=(8000, 2, 2),
amine@88 214 arbitray_sr_multichannel=(5413, 2, 3),
amine@88 215 )
amine@88 216 def test_concatenation(self, sampling_rate, sample_width, channels):
amine@88 217
amine@88 218 region_1, region_2 = _make_random_length_regions(
amine@88 219 [b"a", b"b"], sampling_rate, sample_width, channels
amine@88 220 )
amine@88 221
amine@88 222 expected_start = region_1.start
amine@88 223 expected_duration = region_1.duration + region_2.duration
amine@88 224 expected_end = expected_start + expected_duration
amine@88 225 expected_data = bytes(region_1) + bytes(region_2)
amine@88 226 concat_region = region_1 + region_2
amine@88 227
amine@88 228 self.assertEqual(concat_region.start, expected_start)
amine@88 229 self.assertAlmostEqual(concat_region.end, expected_end, places=6)
amine@88 230 self.assertAlmostEqual(
amine@88 231 concat_region.duration, expected_duration, places=6
amine@88 232 )
amine@88 233 self.assertEqual(bytes(concat_region), expected_data)
amine@88 234 # due to the behavior of `round` len(concat_region) does not always
amine@88 235 # equal len(region_1) + len(region_2)
amine@88 236 # Exmaple if both regions are 1.0005 seconds long, then:
amine@88 237 # len(region_1) == len(region_2) == round(1.0005) == 1000
amine@88 238 # and:
amine@88 239 # region_1.duration + region_2.duration == 1.0005 * 2 = 2.001
amine@88 240 # and:
amine@88 241 # len(region_3) == round(2.001 * 1000) = 2001
amine@88 242 # != len(region_1) + len(region_2)
amine@88 243 self.assertEqual(len(concat_region), round(expected_duration * 1000))
amine@88 244
amine@88 245 @genty_dataset(
amine@88 246 simple=(8000, 1, 1),
amine@88 247 stereo_sw_2=(8000, 2, 2),
amine@88 248 arbitray_sr_multichannel=(5413, 2, 3),
amine@88 249 )
amine@88 250 def test_concatenation_many(self, sampling_rate, sample_width, channels):
amine@88 251
amine@88 252 regions = _make_random_length_regions(
amine@88 253 [b"a", b"b", b"c"], sampling_rate, sample_width, channels
amine@88 254 )
amine@88 255 expected_start = regions[0].start
amine@88 256 expected_duration = sum(r.duration for r in regions)
amine@88 257 expected_end = expected_start + expected_duration
amine@88 258 expected_data = b"".join(bytes(r) for r in regions)
amine@88 259 concat_region = sum(regions)
amine@88 260
amine@88 261 self.assertEqual(concat_region.start, expected_start)
amine@88 262 self.assertAlmostEqual(concat_region.end, expected_end, places=6)
amine@88 263 self.assertAlmostEqual(
amine@88 264 concat_region.duration, expected_duration, places=6
amine@88 265 )
amine@88 266 self.assertEqual(bytes(concat_region), expected_data)
amine@88 267 # see test_concatenation
amine@88 268 self.assertEqual(len(concat_region), round(expected_duration * 1000))
amine@88 269
amine@88 270 def test_concatenation_different_sampling_rate_error(self):
amine@88 271
amine@88 272 region_1 = AudioRegion(b"a" * 100, 0, 8000, 1, 1)
amine@88 273 region_2 = AudioRegion(b"b" * 100, 0, 3000, 1, 1)
amine@88 274
amine@88 275 with self.assertRaises(ValueError) as val_err:
amine@88 276 region_1 + region_2
amine@88 277 self.assertEqual(
amine@88 278 "Can only concatenate AudioRegions of the same "
amine@88 279 "sampling rate (8000 != 3000)",
amine@88 280 str(val_err.exception),
amine@88 281 )
amine@88 282
amine@88 283 def test_concatenation_different_sample_width_error(self):
amine@88 284
amine@88 285 region_1 = AudioRegion(b"a" * 100, 0, 8000, 2, 1)
amine@88 286 region_2 = AudioRegion(b"b" * 100, 0, 8000, 4, 1)
amine@88 287
amine@88 288 with self.assertRaises(ValueError) as val_err:
amine@88 289 region_1 + region_2
amine@88 290 self.assertEqual(
amine@88 291 "Can only concatenate AudioRegions of the same "
amine@88 292 "sample width (2 != 4)",
amine@88 293 str(val_err.exception),
amine@88 294 )
amine@88 295
amine@88 296 def test_concatenation_different_number_of_channels_error(self):
amine@88 297
amine@88 298 region_1 = AudioRegion(b"a" * 100, 0, 8000, 1, 1)
amine@88 299 region_2 = AudioRegion(b"b" * 100, 0, 8000, 1, 2)
amine@88 300
amine@88 301 with self.assertRaises(ValueError) as val_err:
amine@88 302 region_1 + region_2
amine@88 303 self.assertEqual(
amine@88 304 "Can only concatenate AudioRegions of the same "
amine@88 305 "number of channels (1 != 2)",
amine@88 306 str(val_err.exception),
amine@88 307 )