amine@377
|
1 Loading audio data
|
amine@377
|
2 ------------------
|
amine@377
|
3
|
amine@379
|
4 Audio data is loaded with the :func:`load` function which can read from audio
|
amine@379
|
5 files, the microphone or use raw audio data.
|
amine@379
|
6
|
amine@377
|
7 From a file
|
amine@377
|
8 ===========
|
amine@377
|
9
|
amine@379
|
10 If the first argument of :func:`load` is a string, it should be a path to an audio
|
amine@377
|
11 file.
|
amine@369
|
12
|
amine@369
|
13 .. code:: python
|
amine@369
|
14
|
amine@377
|
15 import auditok
|
amine@377
|
16 region = auditok.load("audio.ogg")
|
amine@369
|
17
|
amine@377
|
18 If input file contains a raw (headerless) audio data, passing `audio_format="raw"`
|
amine@377
|
19 and other audio parameters (`sampling_rate`, `sample_width` and `channels`) is
|
amine@377
|
20 mandatory. In the following example we pass audio parameters with their short
|
amine@377
|
21 names:
|
amine@369
|
22
|
amine@369
|
23 .. code:: python
|
amine@369
|
24
|
amine@377
|
25 region = auditok.load("audio.dat",
|
amine@377
|
26 audio_format="raw",
|
amine@379
|
27 sr=44100, # alias for `sampling_rate`
|
amine@379
|
28 sw=2 # alias for `sample_width`
|
amine@379
|
29 ch=1 # alias for `channels`
|
amine@379
|
30 )
|
amine@377
|
31
|
amine@377
|
32 From a `bytes` object
|
amine@377
|
33 =====================
|
amine@377
|
34
|
amine@379
|
35 If the type of the first argument `bytes`, it's interpreted as raw audio data:
|
amine@377
|
36
|
amine@377
|
37 .. code:: python
|
amine@377
|
38
|
amine@377
|
39 sr = 16000
|
amine@377
|
40 sw = 2
|
amine@377
|
41 ch = 1
|
amine@377
|
42 data = b"\0" * sr * sw * ch
|
amine@379
|
43 region = auditok.load(data, sr=sr, sw=sw, ch=ch)
|
amine@377
|
44 print(region)
|
amine@377
|
45
|
amine@377
|
46 output:
|
amine@377
|
47
|
amine@377
|
48 .. code:: bash
|
amine@377
|
49
|
amine@377
|
50 AudioRegion(duration=1.000, sampling_rate=16000, sample_width=2, channels=1)
|
amine@377
|
51
|
amine@377
|
52 From the microphone
|
amine@377
|
53 ===================
|
amine@377
|
54
|
amine@379
|
55 If the first argument is `None`, :func:`load` will try to read data from the
|
amine@379
|
56 microphone. Audio parameters, as well as the `max_read` parameter are mandatory:
|
amine@377
|
57
|
amine@377
|
58
|
amine@377
|
59 .. code:: python
|
amine@377
|
60
|
amine@377
|
61 sr = 16000
|
amine@377
|
62 sw = 2
|
amine@377
|
63 ch = 1
|
amine@377
|
64 five_sec_audio = load(None, sr=sr, sw=sw, ch=ch, max_read=5)
|
amine@377
|
65 print(five_sec_audio)
|
amine@377
|
66
|
amine@377
|
67 output:
|
amine@377
|
68
|
amine@377
|
69 .. code:: bash
|
amine@377
|
70
|
amine@377
|
71 AudioRegion(duration=5.000, sampling_rate=16000, sample_width=2, channels=1)
|
amine@377
|
72
|
amine@377
|
73
|
amine@377
|
74 Skip part of audio data
|
amine@377
|
75 =======================
|
amine@377
|
76
|
amine@379
|
77 If the `skip` parameter is > 0, :func:`load` will skip that leading amount of audio
|
amine@377
|
78 data:
|
amine@377
|
79
|
amine@377
|
80 .. code:: python
|
amine@377
|
81
|
amine@377
|
82 import auditok
|
amine@377
|
83 region = auditok.load("audio.ogg", skip=2) # skip the first 2 seconds
|
amine@377
|
84
|
amine@377
|
85 This argument must be 0 when reading from the microphone.
|
amine@377
|
86
|
amine@377
|
87
|
amine@377
|
88 Basic split example
|
amine@377
|
89 -------------------
|
amine@377
|
90
|
amine@379
|
91 In the following we'll use the :func:`split` function to tokenize an audio file,
|
amine@379
|
92 requiring that valid audio events be at least 0.2 second long, at most 4 seconds
|
amine@379
|
93 long and contain a maximum of 0.3 second of continuous silence. Limiting the size
|
amine@379
|
94 of detected events to 4 seconds means that an event of, say, 9.5 seconds will
|
amine@379
|
95 be returned as two 4-second events plus a third 1.5-second event. Moreover, a
|
amine@379
|
96 valid event might contain many *silences* as far as none of them exceeds 0.3
|
amine@379
|
97 second.
|
amine@379
|
98
|
amine@379
|
99 :func:`split` returns a generator of :class:`AudioRegion`. An :class:`AudioRegion`
|
amine@379
|
100 can be played, saved, repeated (i.e., multiplied by an integer) and concatenated
|
amine@379
|
101 with another region (see examples below). Notice that :class:`AudioRegion` objects
|
amine@379
|
102 returned by :func:`split` have a ``start`` a ``stop`` information stored in
|
amine@379
|
103 their meta data that can be accessed like `object.meta.start`.
|
amine@379
|
104
|
amine@377
|
105 .. code:: python
|
amine@377
|
106
|
amine@377
|
107 import auditok
|
amine@377
|
108
|
amine@377
|
109 # split returns a generator of AudioRegion objects
|
amine@377
|
110 audio_regions = auditok.split(
|
amine@377
|
111 "audio.wav",
|
amine@377
|
112 min_dur=0.2, # minimum duration of a valid audio event in seconds
|
amine@377
|
113 max_dur=4, # maximum duration of an event
|
amine@377
|
114 max_silence=0.3, # maximum duration of tolerated continuous silence within an event
|
amine@377
|
115 energy_threshold=55 # threshold of detection
|
amine@377
|
116 )
|
amine@377
|
117
|
amine@377
|
118 for i, r in enumerate(audio_regions):
|
amine@377
|
119
|
amine@377
|
120 # Regions returned by `split` have 'start' and 'end' metadata fields
|
amine@377
|
121 print("Region {i}: {r.meta.start:.3f}s -- {r.meta.end:.3f}s".format(i=i, r=r))
|
amine@377
|
122
|
amine@377
|
123 # play detection
|
amine@377
|
124 # r.play(progress_bar=True)
|
amine@377
|
125
|
amine@377
|
126 # region's metadata can also be used with the `save` method
|
amine@377
|
127 # (no need to explicitly specify region's object and `format` arguments)
|
amine@377
|
128 filename = r.save("region_{meta.start:.3f}-{meta.end:.3f}.wav")
|
amine@377
|
129 print("region saved as: {}".format(filename))
|
amine@377
|
130
|
amine@377
|
131 output example:
|
amine@377
|
132
|
amine@377
|
133 .. code:: bash
|
amine@377
|
134
|
amine@377
|
135 Region 0: 0.700s -- 1.400s
|
amine@377
|
136 region saved as: region_0.700-1.400.wav
|
amine@377
|
137 Region 1: 3.800s -- 4.500s
|
amine@377
|
138 region saved as: region_3.800-4.500.wav
|
amine@377
|
139 Region 2: 8.750s -- 9.950s
|
amine@377
|
140 region saved as: region_8.750-9.950.wav
|
amine@377
|
141 Region 3: 11.700s -- 12.400s
|
amine@377
|
142 region saved as: region_11.700-12.400.wav
|
amine@377
|
143 Region 4: 15.050s -- 15.850s
|
amine@377
|
144 region saved as: region_15.050-15.850.wav
|
amine@377
|
145
|
amine@377
|
146
|
amine@377
|
147 Split and plot
|
amine@377
|
148 --------------
|
amine@377
|
149
|
amine@377
|
150 Visualize audio signal and detections:
|
amine@377
|
151
|
amine@377
|
152 .. code:: python
|
amine@377
|
153
|
amine@377
|
154 import auditok
|
amine@377
|
155 region = auditok.load("audio.wav") # returns an AudioRegion object
|
amine@377
|
156 regions = region.split_and_plot(...) # or just region.splitp()
|
amine@369
|
157
|
amine@369
|
158 output figure:
|
amine@369
|
159
|
amine@369
|
160 .. image:: figures/example_1.png
|
amine@369
|
161
|
amine@377
|
162
|
amine@377
|
163 Read and split data from the microphone
|
amine@377
|
164 ---------------------------------------
|
amine@377
|
165
|
amine@379
|
166 If the first argument of :func:`split` is None, audio data is read from the
|
amine@379
|
167 microphone (requires `pyaudio <https://people.csail.mit.edu/hubert/pyaudio>`_):
|
amine@377
|
168
|
amine@377
|
169 .. code:: python
|
amine@377
|
170
|
amine@377
|
171 import auditok
|
amine@377
|
172
|
amine@377
|
173 sr = 16000
|
amine@377
|
174 sw = 2
|
amine@377
|
175 ch = 1
|
amine@377
|
176 eth = 55 # alias for energy_threshold, default value is 50
|
amine@377
|
177
|
amine@377
|
178 try:
|
amine@377
|
179 for region in auditok.split(input=None, sr=sr, sw=sw, ch=ch, eth=eth):
|
amine@377
|
180 print(region)
|
amine@377
|
181 region.play(progress_bar=True) # progress bar requires `tqdm`
|
amine@377
|
182 except KeyboardInterrupt:
|
amine@377
|
183 pass
|
amine@377
|
184
|
amine@377
|
185
|
amine@379
|
186 :func:`split` will continue reading audio data until you press ``Ctrl-C``. If
|
amine@379
|
187 you want to read a specific amount of audio data, pass the desired number of
|
amine@379
|
188 seconds with the `max_read` argument.
|
amine@377
|
189
|
amine@377
|
190
|
amine@377
|
191 Accessing recorded data after split
|
amine@377
|
192 -----------------------------------
|
amine@377
|
193
|
amine@379
|
194 Using a :class:`Recorder` object you can get hold of acquired audio data:
|
amine@377
|
195
|
amine@377
|
196
|
amine@377
|
197 .. code:: python
|
amine@377
|
198
|
amine@377
|
199 import auditok
|
amine@377
|
200
|
amine@377
|
201 sr = 16000
|
amine@377
|
202 sw = 2
|
amine@377
|
203 ch = 1
|
amine@377
|
204 eth = 55 # alias for energy_threshold, default value is 50
|
amine@377
|
205
|
amine@377
|
206 rec = auditok.Recorder(input=None, sr=sr, sw=sw, ch=ch)
|
amine@377
|
207
|
amine@377
|
208 try:
|
amine@377
|
209 for region in auditok.split(rec, sr=sr, sw=sw, ch=ch, eth=eth):
|
amine@377
|
210 print(region)
|
amine@377
|
211 region.play(progress_bar=True) # progress bar requires `tqdm`
|
amine@377
|
212 except KeyboardInterrupt:
|
amine@377
|
213 pass
|
amine@377
|
214
|
amine@377
|
215 rec.rewind()
|
amine@377
|
216 full_audio = load(rec.data, sr=sr, sw=sw, ch=ch)
|
amine@379
|
217 # alternatively you can use
|
amine@379
|
218 full_audio = auditok.AudioRegion(rec.data, sr, sw, ch)
|
amine@377
|
219
|
amine@377
|
220
|
amine@379
|
221 :class:`Recorder` also accepts a `max_read` argument.
|
amine@377
|
222
|
amine@369
|
223 Working with AudioRegions
|
amine@369
|
224 -------------------------
|
amine@369
|
225
|
amine@379
|
226 The following are a couple of interesting operations you can do with
|
amine@379
|
227 :class:`AudioRegion` objects.
|
amine@369
|
228
|
amine@377
|
229
|
amine@377
|
230 Basic region information
|
amine@377
|
231 ========================
|
amine@377
|
232
|
amine@377
|
233 .. code:: python
|
amine@377
|
234
|
amine@377
|
235 import auditok
|
amine@377
|
236 region = auditok.load("audio.wav")
|
amine@377
|
237 len(region) # number of audio samples int the regions, one channel considered
|
amine@377
|
238 region.duration # duration in seconds
|
amine@377
|
239 region.sampling_rate # alias `sr`
|
amine@377
|
240 region.sample_width # alias `sw`
|
amine@377
|
241 region.channels # alias `ch`
|
amine@377
|
242
|
amine@377
|
243
|
amine@369
|
244 Concatenate regions
|
amine@369
|
245 ===================
|
amine@369
|
246
|
amine@369
|
247 .. code:: python
|
amine@369
|
248
|
amine@377
|
249 import auditok
|
amine@377
|
250 region_1 = auditok.load("audio_1.wav")
|
amine@377
|
251 region_2 = auditok.load("audio_2.wav")
|
amine@369
|
252 region_3 = region_1 + region_2
|
amine@369
|
253
|
amine@379
|
254 Particularly useful if you want to join regions returned by :func:`split`:
|
amine@369
|
255
|
amine@369
|
256 .. code:: python
|
amine@369
|
257
|
amine@377
|
258 import auditok
|
amine@377
|
259 regions = auditok.load("audio.wav").split()
|
amine@369
|
260 gapless_region = sum(regions)
|
amine@369
|
261
|
amine@369
|
262 Repeat a region
|
amine@369
|
263 ===============
|
amine@369
|
264
|
amine@369
|
265 Multiply by a positive integer:
|
amine@369
|
266
|
amine@369
|
267 .. code:: python
|
amine@369
|
268
|
amine@377
|
269 import auditok
|
amine@377
|
270 region = auditok.load("audio.wav")
|
amine@369
|
271 region_x3 = region * 3
|
amine@369
|
272
|
amine@377
|
273 Split one region into N regions of equal size
|
amine@377
|
274 =============================================
|
amine@369
|
275
|
amine@379
|
276 Divide by a positive integer (this has nothing to do with silence-based
|
amine@379
|
277 tokenization):
|
amine@369
|
278
|
amine@369
|
279 .. code:: python
|
amine@369
|
280
|
amine@377
|
281 import auditok
|
amine@377
|
282 region = auditok.load("audio.wav")
|
amine@369
|
283 regions = regions / 5
|
amine@369
|
284 assert sum(regions) == region
|
amine@369
|
285
|
amine@379
|
286 Note that if no perfect division is possible, the last region might be a bit
|
amine@379
|
287 shorter than the previous N-1 regions.
|
amine@369
|
288
|
amine@377
|
289 Slice a region by samples, seconds or milliseconds
|
amine@377
|
290 ==================================================
|
amine@377
|
291
|
amine@379
|
292 Slicing an :class:`AudioRegion` can be interesting in many situations. You can for
|
amine@377
|
293 example remove a fixed-size portion of audio data from the beginning or from the
|
amine@377
|
294 end of a region or crop a region by an arbitrary amount as a data augmentation
|
amine@379
|
295 strategy.
|
amine@369
|
296
|
amine@377
|
297 The most accurate way to slice an `AudioRegion` is to use indices that
|
amine@369
|
298 directly refer to raw audio samples. In the following example, assuming that the
|
amine@369
|
299 sampling rate of audio data is 16000, you can extract a 5-second region from
|
amine@369
|
300 main region, starting from the 20th second as follows:
|
amine@369
|
301
|
amine@369
|
302 .. code:: python
|
amine@369
|
303
|
amine@377
|
304 import auditok
|
amine@377
|
305 region = auditok.load("audio.wav")
|
amine@369
|
306 start = 20 * 16000
|
amine@369
|
307 stop = 25 * 16000
|
amine@369
|
308 five_second_region = region[start:stop]
|
amine@369
|
309
|
amine@379
|
310 This allows you to practically start and stop at any audio sample within the region.
|
amine@369
|
311 Just as with a `list` you can omit one of `start` and `stop`, or both. You can
|
amine@369
|
312 also use negative indices:
|
amine@369
|
313
|
amine@369
|
314 .. code:: python
|
amine@369
|
315
|
amine@377
|
316 import auditok
|
amine@377
|
317 region = auditok.load("audio.wav")
|
amine@369
|
318 start = -3 * region.sr # `sr` is an alias of `sampling_rate`
|
amine@369
|
319 three_last_seconds = region[start:]
|
amine@369
|
320
|
amine@379
|
321 While slicing by raw samples is flexible, slicing with temporal indices is more
|
amine@379
|
322 intuitive. You can do so by accessing the ``millis`` or ``seconds`` views of an
|
amine@377
|
323 `AudioRegion` (or their shortcut alias `ms` and `sec` or `s`).
|
amine@369
|
324
|
amine@379
|
325 With the ``millis`` view:
|
amine@369
|
326
|
amine@369
|
327 .. code:: python
|
amine@369
|
328
|
amine@377
|
329 import auditok
|
amine@377
|
330 region = auditok.load("audio.wav")
|
amine@369
|
331 five_second_region = region.millis[5000:10000]
|
amine@369
|
332
|
amine@379
|
333 or with the ``seconds`` view:
|
amine@369
|
334
|
amine@369
|
335 .. code:: python
|
amine@369
|
336
|
amine@377
|
337 import auditok
|
amine@377
|
338 region = auditok.load("audio.wav")
|
amine@369
|
339 five_second_region = region.seconds[5:10]
|
amine@369
|
340
|
amine@379
|
341 ``seconds`` indices can also be floats:
|
amine@369
|
342
|
amine@369
|
343 .. code:: python
|
amine@369
|
344
|
amine@377
|
345 import auditok
|
amine@377
|
346 region = auditok.load("audio.wav")
|
amine@377
|
347 five_second_region = region.seconds[2.5:7.5]
|
amine@377
|
348
|
amine@377
|
349 Get arrays of audio samples
|
amine@377
|
350 ===========================
|
amine@377
|
351
|
amine@377
|
352 If `numpy` is not installed, the `samples` attributes is a list of audio samples
|
amine@377
|
353 arrays (standard `array.array` objects), one per channels. If numpy is installed,
|
amine@377
|
354 `samples` is a 2-D `numpy.ndarray` where the fist dimension is the channel
|
amine@377
|
355 and the second is the the sample.
|
amine@377
|
356
|
amine@377
|
357 .. code:: python
|
amine@377
|
358
|
amine@377
|
359 import auditok
|
amine@377
|
360 region = auditok.load("audio.wav")
|
amine@369
|
361 samples = region.samples
|
amine@379
|
362 assert len(samples) == region.channels
|
amine@369
|
363
|
amine@369
|
364
|
amine@377
|
365 If `numpy` is not installed you can use:
|
amine@369
|
366
|
amine@369
|
367 .. code:: python
|
amine@369
|
368
|
amine@369
|
369 import numpy as np
|
amine@377
|
370 region = auditok.load("audio.wav")
|
amine@369
|
371 samples = np.asarray(region)
|
amine@377
|
372 assert len(samples.shape) == 2
|