Ejemplo n.º 1
0
def separate_channels(data, fmt, channels):
    """Create a list of arrays of audio samples (`array.array` objects), one for
    each channel.

    Parameters
    ----------
    data : bytes
        multi-channel audio data to mix down.
    fmt : str
        format (single character) to pass to `array.array` to convert `data`
        into an array of samples. This should be "b" if audio data's sample width
        is 1, "h" if it's 2 and "i" if it's 4.
    channels : int
        number of channels of audio data.

    Returns
    -------
    channels_arr : list
        list of audio channels, each as a standard `array.array`.
    """
    all_channels = array_(fmt, data)
    mono_channels = [
        array_(fmt, all_channels[ch::channels]) for ch in range(channels)
    ]
    return mono_channels
Ejemplo n.º 2
0
def compute_average_channel(data, fmt, channels):
    """
    Compute and return average channel of multi-channel audio data. If the
    number of channels is 2, use :func:`compute_average_channel_stereo` (much
    faster). This function uses satandard `array` module to convert `bytes` data
    into an array of numeric values.

    Parameters
    ----------
    data : bytes
        multi-channel audio data to mix down.
    fmt : str
        format (single character) to pass to `array.array` to convert `data`
        into an array of samples. This should be "b" if audio data's sample width
        is 1, "h" if it's 2 and "i" if it's 4.
    channels : int
        number of channels of audio data.

    Returns
    -------
    mono_audio : bytes
        mixed down audio data.
    """
    all_channels = array_(fmt, data)
    mono_channels = [
        array_(fmt, all_channels[ch::channels]) for ch in range(channels)
    ]
    avg_arr = array_(
        fmt,
        (round(sum(samples) / channels) for samples in zip(*mono_channels)),
    )
    return avg_arr
Ejemplo n.º 3
0
    def test_make_channel_selector_one_channel(self, sample_width, channels,
                                               selected, expected):

        # force using signal functions with standard python implementation
        with patch("auditok.util.signal", signal_):
            selector = make_channel_selector(sample_width, channels, selected)
            result = selector(self.data)

        fmt = signal_.FORMAT[sample_width]
        expected = array_(fmt, expected)
        if channels == 1:
            expected = bytes(expected)
        self.assertEqual(result, expected)

        # Use signal functions with numpy implementation
        with patch("auditok.util.signal", signal_numpy):
            selector = make_channel_selector(sample_width, channels, selected)
            result_numpy = selector(self.data)

        expected = array_(fmt, expected)
        if channels == 1:
            expected = bytes(expected)
            self.assertEqual(result_numpy, expected)
        else:
            self.assertTrue(all(result_numpy == expected))
Ejemplo n.º 4
0
 def test_to_array(self, sample_width, expected):
     if isinstance(expected[0], list):
         channels = len(expected)
         expected = [
             array_(signal_.FORMAT[sample_width], xi) for xi in expected
         ]
     else:
         channels = 1
         expected = array_(signal_.FORMAT[sample_width], expected)
     resutl = signal_.to_array(self.data, sample_width, channels)
     resutl_numpy = signal_numpy.to_array(self.data, sample_width, channels)
     self.assertEqual(resutl, expected)
     self.assertTrue((resutl_numpy == np.asarray(expected)).all())
     self.assertEqual(resutl_numpy.dtype, np.float64)
Ejemplo n.º 5
0
 def test_compute_average_channel(self, fmt, channels, expected):
     result = signal_.compute_average_channel(self.data, fmt, channels)
     expected = array_(fmt, expected)
     expected_numpy_fmt = self.numpy_fmt[fmt]
     self.assertEqual(result, expected)
     result_numpy = signal_numpy.compute_average_channel(
         self.data, self.numpy_fmt[fmt], channels)
     self.assertTrue(all(result_numpy == expected))
     self.assertEqual(result_numpy.dtype, expected_numpy_fmt)
Ejemplo n.º 6
0
 def test_extract_single_channel(self, fmt, channels, selected, expected):
     resutl = signal_.extract_single_channel(self.data, fmt, channels,
                                             selected)
     expected = array_(fmt, expected)
     expected_numpy_fmt = self.numpy_fmt[fmt]
     self.assertEqual(resutl, expected)
     resutl_numpy = signal_numpy.extract_single_channel(
         self.data, self.numpy_fmt[fmt], channels, selected)
     self.assertTrue(all(resutl_numpy == expected))
     self.assertEqual(resutl_numpy.dtype, expected_numpy_fmt)
Ejemplo n.º 7
0
    def test_calculate_energy_multichannel(self, x, sample_width,
                                           aggregation_fn, expected):
        x = [array_(signal_.FORMAT[sample_width], xi) for xi in x]
        energy = signal_.calculate_energy_multichannel(x, sample_width,
                                                       aggregation_fn)
        self.assertEqual(energy, expected)

        energy = signal_numpy.calculate_energy_multichannel(
            x, sample_width, aggregation_fn)
        self.assertEqual(energy, expected)
Ejemplo n.º 8
0
 def test_to_array(self, sample_width, expected):
     channels = len(expected)
     expected = [
         array_(signal_.FORMAT[sample_width], xi) for xi in expected
     ]
     result = signal_.to_array(self.data, sample_width, channels)
     result_numpy = signal_numpy.to_array(self.data, sample_width, channels)
     self.assertEqual(result, expected)
     self.assertTrue((result_numpy == np.asarray(expected)).all())
     self.assertEqual(result_numpy.dtype, np.float64)
Ejemplo n.º 9
0
    def test_separate_channels(self, fmt, channels, expected):
        resutl = signal_.separate_channels(self.data, fmt, channels)
        expected = [array_(fmt, exp) for exp in expected]
        expected_numpy_fmt = self.numpy_fmt[fmt]
        self.assertEqual(resutl, expected)

        resutl_numpy = signal_numpy.separate_channels(self.data,
                                                      self.numpy_fmt[fmt],
                                                      channels)
        self.assertTrue((resutl_numpy == expected).all())
        self.assertEqual(resutl_numpy.dtype, expected_numpy_fmt)
Ejemplo n.º 10
0
    def test_audio_energy_validator(self, data, channels, use_channel,
                                    expected):

        data = array_("h", data)
        sample_width = 2
        energy_threshold = 50
        validator = AudioEnergyValidator(energy_threshold, sample_width,
                                         channels, use_channel)

        if expected:
            self.assertTrue(validator.is_valid(data))
        else:
            self.assertFalse(validator.is_valid(data))
Ejemplo n.º 11
0
def compute_average_channel_stereo(data, sample_width):
    """Compute and return average channel of stereo audio data. This function
    should be used when the number of channels is exactly 2 because in that
    case we can use standard `audioop` module which *much* faster then calling
    :func:`compute_average_channel`.

    Parameters
    ----------
    data : bytes
        2-channel audio data to mix down.
    sample_width : int
        size in bytes of one audio sample (one channel considered).

    Returns
    -------
    mono_audio : bytes
        mixed down audio data.
    """
    fmt = FORMAT[sample_width]
    arr = array_(fmt, audioop.tomono(data, sample_width, 0.5, 0.5))
    return arr
Ejemplo n.º 12
0
def to_array(data, sample_width, channels):
    """Extract individual channels of audio data and return a list of arrays of
    numeric samples. This will always return a list of `array.array` objects
    (one per channel) even if audio data is mono.

    Parameters
    ----------
    data : bytes
        raw audio data.
    sample_width : int
        size in bytes of one audio sample (one channel considered).

    Returns
    -------
    samples_arrays : list
        list of arrays of audio samples.
    """
    fmt = FORMAT[sample_width]
    if channels == 1:
        return [array_(fmt, data)]
    return separate_channels(data, fmt, channels)
Ejemplo n.º 13
0
def _generate_pure_tone(frequency,
                        duration_sec=1,
                        sampling_rate=16000,
                        sample_width=2,
                        volume=1e4):
    """
    Generates a pure tone with the given frequency.
    """
    assert frequency <= sampling_rate / 2
    max_value = (2**(sample_width * 8) // 2) - 1
    if volume > max_value:
        volume = max_value
    fmt = signal_.FORMAT[sample_width]
    total_samples = int(sampling_rate * duration_sec)
    step = frequency / sampling_rate
    two_pi_step = 2 * math.pi * step
    data = array_(
        fmt,
        (int(math.sin(two_pi_step * i) * volume)
         for i in range(total_samples)),
    )
    return data
Ejemplo n.º 14
0
def extract_single_channel(data, fmt, channels, selected):
    samples = array_(fmt, data)
    return samples[selected::channels]
Ejemplo n.º 15
0
 def test_calculate_energy_single_channel(self, x, sample_width, expected):
     x = array_(signal_.FORMAT[sample_width], x)
     energy = signal_.calculate_energy_single_channel(x, sample_width)
     self.assertEqual(energy, expected)
     energy = signal_numpy.calculate_energy_single_channel(x, sample_width)
     self.assertEqual(energy, expected)
Ejemplo n.º 16
0
 def test_compute_average_channel_stereo(self, sample_width, expected):
     result = signal_.compute_average_channel_stereo(
         self.data, sample_width)
     fmt = signal_.FORMAT[sample_width]
     expected = array_(fmt, expected)
     self.assertEqual(result, expected)