changeset 415:e26dcf224846

implement 'make_silence'
author Amine Sehili <amine.sehili@gmail.com>
date Wed, 16 Oct 2024 20:08:37 +0200
parents 9f83c1ecb03b
children 14efef6f4bae
files auditok/core.py tests/test_core.py
diffstat 2 files changed, 56 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/auditok/core.py	Tue Oct 15 21:56:12 2024 +0200
+++ b/auditok/core.py	Wed Oct 16 20:08:37 2024 +0200
@@ -24,7 +24,7 @@
 except ImportError:
     from . import signal
 
-__all__ = ["load", "split", "AudioRegion", "StreamTokenizer"]
+__all__ = ["load", "split", "make_silence", "AudioRegion", "StreamTokenizer"]
 
 
 DEFAULT_ANALYSIS_WINDOW = 0.05
@@ -183,7 +183,7 @@
     max_read, mr : float, default: None, read until end of stream
         maximum data to read from source in seconds.
     validator, val : callable, DataValidator
-        custom data validator. If `None` (default), an `AudioEnergyValidtor` is
+        custom data validator. If `None` (default), an `AudioEnergyValidator` is
         used with the given energy threshold. Can be a callable or an instance
         of `DataValidator` that implements `is_valid`. In either case, it'll be
         called with with a window of audio data as the first parameter.
@@ -308,6 +308,31 @@
     return region_gen
 
 
+def make_silence(duration, sampling_rate=16000, sample_width=2, channels=1):
+    """Generate a silence of a specific  duration.
+
+    Parameters
+    ----------
+    duration : float
+        silence duration in seconds.
+    sampling_rate : int, optional
+        sampling rate of audio data, by default 16000.
+    sample_width : int, optional
+        number of bytes used to encode one audio sample, by default 2.
+    channels : int, optional
+        number of channels of audio data, by default 1.
+
+    Returns
+    -------
+    AudioRegion
+        a "silent" AudioRegion of the desired duration.
+    """
+    size = round(duration * sampling_rate) * sample_width * channels
+    data = b"\0" * size
+    region = AudioRegion(data, sampling_rate, sample_width, channels)
+    return region
+
+
 def _duration_to_nb_windows(
     duration, analysis_window, round_fn=round, epsilon=0
 ):
@@ -398,10 +423,6 @@
         maximum amount of data to read in seconds.
     kwargs :
         audio parameters (sampling_rate, sample_width and channels).
-
-    See also
-    --------
-    `AudioRegion.build`
     """
     reader = AudioReader(None, block_dur=0.5, max_read=max_read, **kwargs)
     reader.open()
@@ -442,11 +463,6 @@
         end of stream.
     kwargs :
         audio parameters (sampling_rate, sample_width and channels).
-
-    See also
-    --------
-    `AudioRegion.build`
-
     """
     audio_source = get_audio_source(input, **kwargs)
     audio_source.open()
--- a/tests/test_core.py	Tue Oct 15 21:56:12 2024 +0200
+++ b/tests/test_core.py	Wed Oct 16 20:08:37 2024 +0200
@@ -8,7 +8,7 @@
 import numpy as np
 import pytest
 
-from auditok import AudioParameterError, AudioRegion, load, split
+from auditok import AudioParameterError, AudioRegion, load, make_silence, split
 from auditok.core import (
     _duration_to_nb_windows,
     _make_audio_region,
@@ -77,6 +77,34 @@
 
 
 @pytest.mark.parametrize(
+    "duration, sampling_rate, sample_width, channels",
+    [
+        (1.05, 16000, 1, 1),  # mono_16K_1byte
+        (1.5, 16000, 2, 1),  # mono_16K_2byte
+        (1.0001, 44100, 2, 2),  # stereo_44100_2byte
+        (1.000005, 48000, 2, 3),  # 3channel_48K_2byte
+        (1.0001, 48000, 4, 4),  # 4channel_48K_4byte
+        (0, 48000, 4, 4),  # 4channel_4K_4byte_0sec
+    ],
+    ids=[
+        "mono_16K_1byte",
+        "mono_16K_2byte",
+        "stereo_44100_2byte",
+        "3channel_48000_2byte",
+        "4channel_48K_4byte",
+        "4channel_4K_4byte_0sec",
+    ],
+)
+def test_make_silence(duration, sampling_rate, sample_width, channels):
+    silence = make_silence(duration, sampling_rate, sample_width, channels)
+    size = round(duration * sampling_rate) * sample_width * channels
+    expected_data = b"\0" * size
+    expected_duration = size / (sampling_rate * sample_width * channels)
+    assert silence.duration == expected_duration
+    assert silence.data == expected_data
+
+
+@pytest.mark.parametrize(
     "duration, analysis_window, round_fn, expected, kwargs",
     [
         (0, 1, None, 0, None),  # zero_duration