Пример #1
0
def audio_data_converter(raw_data: bytes, in_settings: AudioSettings,
                         out_settings: AudioSettings) -> bytes:
    in_sample_rate = in_settings.sample_rate
    out_sample_rate = out_settings.sample_rate
    in_sample_width = in_settings.sample_width
    out_sample_width = out_settings.sample_width

    if in_settings.channels != out_settings.channels:
        raise RuntimeError(
            'Can not convert audio data. The number of channels must be the same.'
        )

    if in_sample_rate == out_sample_rate and in_sample_width == out_sample_width:
        return raw_data

    # make sure unsigned 8-bit audio (which uses unsigned samples)
    # is handled like higher sample width audio (which uses signed samples)
    if in_sample_width == 1:
        # subtract 128 from every sample to make them act like signed samples
        raw_data = audioop.bias(raw_data, 1, -128)

    if in_sample_rate != out_sample_rate:
        raw_data, _ = audioop.ratecv(raw_data, in_sample_width,
                                     in_settings.channels, in_sample_rate,
                                     out_sample_rate, None)

    if in_sample_width != out_sample_width:
        # we're converting the audio into 24-bit
        # workaround for https://bugs.python.org/issue12866
        if out_sample_width == 3:
            # convert audio into 32-bit first, which is always supported
            raw_data = audioop.lin2lin(raw_data, in_sample_width, 4)
            try:
                # test whether 24-bit audio is supported
                # for example, ``audioop`` in Python 3.3 and below don't support
                # sample width 3, while Python 3.4+ do
                audioop.bias(b"", 3, 0)
            except audioop.error:
                # this version of audioop doesn't support 24-bit audio
                # (probably Python 3.3 or less)
                #
                # since we're in little endian,
                # we discard the first byte from each 32-bit sample to get a 24-bit sample
                raw_data = b"".join(raw_data[i + 1:i + 4]
                                    for i in range(0, len(raw_data), 4))
            else:
                # 24-bit audio fully supported, we don't need to shim anything
                raw_data = audioop.lin2lin(raw_data, in_sample_width,
                                           out_sample_width)
        else:
            raw_data = audioop.lin2lin(raw_data, in_sample_width,
                                       out_sample_width)

    # if the output is 8-bit audio with unsigned samples,
    # convert the samples we've been treating as signed to unsigned again
    if out_sample_width == 1:
        # add 128 to every sample to make them act like unsigned samples again
        raw_data = audioop.bias(raw_data, 1, 128)

    return raw_data
Пример #2
0
    def get_raw_data(self, convert_rate=None, convert_width=None):
        """
        Returns a byte string representing the raw frame data for the audio represented by the ``AudioData`` instance.
        If ``convert_rate`` is specified and the audio sample rate is not ``convert_rate`` Hz, the resulting audio is
        resampled to match. If ``convert_width`` is specified and the audio samples are not ``convert_width`` bytes
        each, the resulting audio is converted to match. Writing these bytes directly to a file results in a valid
        `RAW/PCM audio file <https://en.wikipedia.org/wiki/Raw_audio_format>`__.
        """
        assert convert_rate is None or convert_rate > 0, "Sample rate to convert to must be a positive integer"
        assert convert_width is None or (
            convert_width % 1 == 0 and 1 <= convert_width <= 4
        ), "Sample width to convert to must be between 1 and 4 inclusive"

        raw_data = self.frame_data

        # make sure unsigned 8-bit audio (which uses unsigned samples) is handled like higher sample width audio
        # (which uses signed samples)
        if self.sample_width == 1:
            raw_data = audioop.bias(
                raw_data, 1, -128
            )  # subtract 128 from every sample to make them act like signed
            # samples

        # resample audio at the desired rate if specified
        if convert_rate is not None and self.sample_rate != convert_rate:
            raw_data, _ = audioop.ratecv(raw_data, self.sample_width, 1,
                                         self.sample_rate, convert_rate, None)

        # convert samples to desired sample width if specified
        if convert_width is not None and self.sample_width != convert_width:
            if convert_width == 3:  # we're converting the audio into 24-bit (workaround for https://bugs.python.org/issue12866)
                raw_data = audioop.lin2lin(
                    raw_data, self.sample_width, 4
                )  # convert audio into 32-bit first, which is always supported
                try:
                    audioop.bias(
                        b"", 3, 0
                    )  # test whether 24-bit audio is supported (for example, ``audioop`` in Python 3.3 and below don't support sample width 3, while Python 3.4+ do)
                except audioop.error:  # this version of audioop doesn't support 24-bit audio (probably Python 3.3 or less)
                    raw_data = b"".join(
                        raw_data[i + 1:i + 4]
                        for i in range(0, len(raw_data), 4)
                    )  # since we're in little endian, we discard the first byte from each 32-bit sample to get a 24-bit sample
                else:  # 24-bit audio fully supported, we don't need to shim anything
                    raw_data = audioop.lin2lin(raw_data, self.sample_width,
                                               convert_width)
            else:
                raw_data = audioop.lin2lin(raw_data, self.sample_width,
                                           convert_width)

        # if the output is 8-bit audio with unsigned samples, convert the samples we've been treating as signed to unsigned again
        if convert_width == 1:
            raw_data = audioop.bias(
                raw_data, 1, 128
            )  # add 128 to every sample to make them act like unsigned samples again

        return raw_data
    def get_raw_data(self, convert_rate=None, convert_width=None):
        """
        返回一个字节字符串,表示AudioData实例音频的原始帧数据。
        如果``convert_rate``已经被指定并且音频采样率不是指定的``convert_rate`` Hz,则重新采样生成的音频以达到匹配。
        如果``convert_width``已经被指定并且音频采样不是指定的``convert_width``字节,则转换生成的音频以达到匹配。
        将这些字节直接写入文件会生成有效的RAW / PCM音频文件 <https://en.wikipedia.org/wiki/Raw_audio_format>`__.
        """
        #@noter:崔冰
        #@description:将采样率和样本宽度都转换成指定数值,获得原始音频数据
        #@param string convert_rate:需转换成的采样率
        #@param string convert_width:需转换成的样本宽度
        #@return 返回一个字节字符串,表示AudioData实例音频的原始帧数据
        assert convert_rate is None or convert_rate > 0, "Sample rate to convert to must be a positive integer"  #需要转换成的采样率必须是正整数
        assert convert_width is None or (
            convert_width % 1 == 0 and 1 <= convert_width <= 4
        ), "Sample width to convert to must be between 1 and 4 inclusive"  #需要转换成的采样宽度必须在1——4之间(包括1和4)

        raw_data = self.frame_data

        # 确保无符号的8位音频(使用无符号样本) 被处理为更高采样宽度的音频 (使用有符号样本)
        if self.sample_width == 1:
            raw_data = audioop.bias(raw_data, 1,
                                    -128)  # 从每个样本中减去128,使它们像有符号样本一样

        # 若指定了所需采样率,就重采样音频
        if convert_rate is not None and self.sample_rate != convert_rate:
            raw_data, _ = audioop.ratecv(raw_data, self.sample_width, 1,
                                         self.sample_rate, convert_rate, None)

        # 若指定了样本宽度,将样本转换成所需样本宽度,
        if convert_width is not None and self.sample_width != convert_width:
            if convert_width == 3:  # 将音频转换成24位 (解决方法 https://bugs.python.org/issue12866)
                raw_data = audioop.lin2lin(raw_data, self.sample_width,
                                           4)  # 先把音频转换成32位
                try:
                    audioop.bias(
                        b"", 3, 0
                    )  # 测试一下支不支持24位音频 (例如,Python 3.3及以下的``audioop`` 不支持样本宽度3, 但 Python 3.4+ 可以)
                except audioop.error:  # 这个版本的audioop d不支持24位音频 (可能是Python 3.3 及以下的版本)
                    raw_data = b"".join(
                        raw_data[i + 1:i + 4]
                        for i in range(0, len(raw_data), 4)
                    )  # 由于我们处于小端,因此我们丢弃每个32位采样的第一个字节以获得24位采样
                else:  # 24位音频完全支持,我们不需要填充任何东西
                    raw_data = audioop.lin2lin(raw_data, self.sample_width,
                                               convert_width)
            else:
                raw_data = audioop.lin2lin(raw_data, self.sample_width,
                                           convert_width)

        # 如果输出是无符号样本的8位音频,则将我们以前当作有符号样本处理的样本转换为无符号样本
        if convert_width == 1:
            raw_data = audioop.bias(raw_data, 1,
                                    128)  # 为每个样本添加128,使其再次像无符号样本一样

        return raw_data
Пример #4
0
def downsample(buf, outrate=16000):
    """Downsample audio. Required for voice detection.

    :param buf: Audio data buffer (or path to WAV file).
    :param int outrate: Output audio sample rate in Hz.
    :returns: Output buffer.
    :rtype: BytesIO

    """
    wav = wave.open(buf)
    inpars = wav.getparams()
    frames = wav.readframes(inpars.nframes)

    # Convert to mono
    if inpars.nchannels == 2:
        frames = audioop.tomono(frames, inpars.sampwidth, 1, 1)

    # Convert to 16-bit depth
    if inpars.sampwidth > 2:
        frames = audioop.lin2lin(frames, inpars.sampwidth, 2)

    # Convert frame rate to 16000 Hz
    frames, _ = audioop.ratecv(frames, 2, 1, inpars.framerate, outrate, None)

    # Return a BytesIO version of the output
    outbuf = BytesIO()
    out = wave.open(outbuf, "w")
    out.setnchannels(1)
    out.setsampwidth(2)
    out.setframerate(outrate)
    out.writeframes(frames)
    out.close()
    outbuf.seek(0)
    return outbuf
Пример #5
0
 def test_lin2lin(self):
     # too simple: we test only the size
     for d1 in data:
         for d2 in data:
             got = len(d1) // 3
             wtd = len(d2) // 3
             self.assertEqual(len(audioop.lin2lin(d1, got, wtd)), len(d2))
Пример #6
0
    def openWavAndConvertDown(self, path):
        import wave
        import audioop

        try:
            waveInput = wave.open(path, "rb")
        except:
            import soundfile

            data, samplerate = soundfile.read('temp/temp.wav')
            soundfile.write('temp/temp.wav', data, samplerate, subtype='PCM_16')
            waveInput = wave.open(path, "rb")

        converted = waveInput.readframes(waveInput.getnframes())

        if waveInput.getframerate() != 8000:
            converted = audioop.ratecv(converted, waveInput.getsampwidth(), waveInput.getnchannels(),
                                       waveInput.getframerate(), 8000, None)
            converted = converted[0]

        if waveInput.getnchannels() == 2:
            converted = audioop.tomono(converted, waveInput.getsampwidth(), 0.5, 0.5)

        if waveInput.getsampwidth() > 1:
            converted = audioop.lin2lin(converted, waveInput.getsampwidth(), 1)
            converted = audioop.bias(converted, 1, 128)

        waveInput.close()

        waveOutput = wave.open("temp/temp.wav", "wb")
        waveOutput.setnchannels(1)
        waveOutput.setsampwidth(1)
        waveOutput.setframerate(8000)
        waveOutput.writeframes(converted)
        waveOutput.close()
Пример #7
0
    def raw_read(self):
        """Return some amount of data as a raw audio string"""
        buf = self.source.raw_read()
        if buf is None:
            self.eof = True
            return None

        # Convert channels as needed
        if self.set_channels and self.source.channels() != self.set_channels:
            if self.set_channels == 1:
                buf = audioop.tomono(buf, self.source.raw_width(), .5, .5)
            else:
                buf = audioop.tostereo(buf, self.source.raw_width(), 1, 1)

        # Convert sampling rate as needed
        if self.set_sampling_rate and self.source.sampling_rate() != self.set_sampling_rate:
            (buf, self.ratecv_state) = audioop.ratecv(buf, self.source.raw_width(), self.channels(), self.source.sampling_rate(), self.set_sampling_rate, self.ratecv_state)

        if self.set_raw_width and self.source.raw_width() != self.set_raw_width:
            if self.source.raw_width() == 1 and self.source.has_unsigned_singles():
                buf = audioop.bias(buf, 1, -128)
            buf = audioop.lin2lin(buf, self.source.raw_width(), self.set_raw_width)
            if self.set_raw_width == 1 and self.source.has_unsigned_singles():
                buf = audioop.bias(buf, 1, 128)

        return buf
Пример #8
0
    def convert_to(self,
                   data: bytes,
                   to_depth: int,
                   to_channels: int,
                   to_rate: int,
                   to_unsigned: bool = False) -> bytes:
        """Convert audio data."""
        dest_width = to_depth // 8

        print(to_depth, self._depth)
        if self._depth != to_depth:
            if self._depth == 8:
                data = audioop.bias(data, 1, 128)
            data = audioop.lin2lin(data, self._width, dest_width)
            if to_depth == 8:
                data = audioop(data, 1, 128)

        if self._unsigned != to_unsigned:
            data = audioop.bias(data, dest_width, 128)

        # Make it stereo
        if self._channels < to_channels:
            data = audioop.tostereo(data, dest_width, 1, 1)
        # Make it mono
        elif self._channels > to_channels:
            data = audioop.tomono(data, dest_width, 1, 1)

        # print(dest_width)
        # Convert the sample rate of the data to the requested rate.
        if self._rate != to_rate and data:
            data, self._state = audioop.ratecv(data, dest_width, to_channels,
                                               self._rate, to_rate,
                                               self._state, 2, 1)

        return data
Пример #9
0
def convert_sampwidth(fragment, sampwidth_in, sampwidth_out):
    """
    Convert the sampwidth (byte width) of the input fragment between 1-, 2-, 3-, 4-byte formats.

    Parameters
    ----------
    fragment : bytes object
        Specifies the original fragment.
    sampwidth_in : int
        Specifies the fragment's original sampwidth.
    sampwidth_out : int
        Specifies the fragment's desired sampwidth.

    Returns
    -------
    bytes

    """
    if sampwidth_in == sampwidth_out:
        return fragment

    # In .wav files, 16, 24, and 32 bit samples are signed, 8 bit samples are unsigned.
    # So when converting from 8 bit wide samples, you need to also subtract 128 from the sample.
    # Similarly, when converting to 8 bit wide samples, you need to also add 128 to the result.
    if sampwidth_in == 1:
        new_fragment = audioop.bias(fragment, 1, -128)
    else:
        new_fragment = fragment
    new_fragment = audioop.lin2lin(new_fragment, sampwidth_in, sampwidth_out)
    if sampwidth_out == 1:
        new_fragment = audioop.bias(new_fragment, 1, 128)
    return new_fragment
Пример #10
0
    def get_raw_data(self, convert_rate = None, convert_width = None):
        """
        Returns a byte string representing the raw frame data for the audio represented by the ``AudioData`` instance.

        If ``convert_rate`` is specified and the audio sample rate is not ``convert_rate`` Hz, the resulting audio is resampled to match.

        If ``convert_width`` is specified and the audio samples are not ``convert_width`` bytes each, the resulting audio is converted to match.

        Writing these bytes directly to a file results in a valid `RAW/PCM audio file <https://en.wikipedia.org/wiki/Raw_audio_format>`__.
        """
        assert convert_rate is None or convert_rate > 0, "Sample rate to convert to must be a positive integer"
        assert convert_width is None or (convert_width % 1 == 0 and 1 <= convert_width <= 4), "Sample width to convert to must be between 1 and 4 inclusive"

        raw_data = self.frame_data

        # make sure unsigned 8-bit audio (which uses unsigned samples) is handled like higher sample width audio (which uses signed samples)
        if self.sample_width == 1:
            raw_data = audioop.bias(raw_data, 1, -128) # subtract 128 from every sample to make them act like signed samples

        # resample audio at the desired rate if specified
        if convert_rate is not None and self.sample_rate != convert_rate:
            raw_data, _ = audioop.ratecv(raw_data, self.sample_width, 1, self.sample_rate, convert_rate, None)
            pass

        # convert samples to desired byte format if specified
        if convert_width is not None and self.sample_width != convert_width:
            raw_data = audioop.lin2lin(raw_data, self.sample_width, convert_width)

        # if the output is 8-bit audio with unsigned samples, convert the samples we've been treating as signed to unsigned again
        if convert_width == 1:
            raw_data = audioop.bias(raw_data, 1, 128) # add 128 to every sample to make them act like unsigned samples again

        return raw_data
Пример #11
0
 def test_lin2lin(self):
     # too simple: we test only the size
     for d1 in data:
         for d2 in data:
             got = len(d1)//3
             wtd = len(d2)//3
             self.assertEqual(len(audioop.lin2lin(d1, got, wtd)), len(d2))
Пример #12
0
def coerce_lin(source_aiff, template_obj):
  '''Read data from source, and convert it to match template's params.'''
  import audioop
  frag = source_aiff.read_lin()
  Ss = source_aiff.stream
  St = template_obj.stream

  # Sample width
  if Ss.getsampwidth() != St.getsampwidth():
    print 'coerce sampwidth %i -> %i' %(Ss.getsampwidth(), St.getsampwidth())
    frag = audioop.lin2lin(frag, Ss.getsampwidth(), St.getsampwidth())
  width = St.getsampwidth()

  # Channels
  if Ss.getnchannels() != St.getnchannels():
    print 'coerce nchannels %i -> %i' %(Ss.getnchannels(), St.getnchannels())
    if Ss.getnchannels()==2 and St.getnchannels()==1:
      frag = audioop.tomono(frag, width, 0.5, 0.5)
    elif Ss.getnchannels()==1 and St.getnchannels()==2:
      frag = audioop.tostereo(frag, width, 1.0, 1.0)
    else:
      print "Err: can't match channels"

  # Frame rate
  if Ss.getframerate() != St.getframerate():
    print 'coerce framerate %i -> %i' %(Ss.getframerate(), St.getframerate())
    frag,state = audioop.ratecv(
        frag, width,
        St.getnchannels(),
        Ss.getframerate(), # in rate
        St.getframerate(), # out rate
        None, 2,1
      )
  return frag
Пример #13
0
    def get_raw_data(self, convert_rate=None, convert_width=None):
        """
        Returns a byte string representing the raw frame data for the audio represented by the ``AudioData`` instance.

        If ``convert_rate`` is specified and the audio sample rate is not ``convert_rate`` Hz, the resulting audio is resampled to match.

        If ``convert_width`` is specified and the audio samples are not ``convert_width`` bytes each, the resulting audio is converted to match.

        Writing these bytes directly to a file results in a valid `RAW/PCM audio file <https://en.wikipedia.org/wiki/Raw_audio_format>`__.
        """
        assert convert_rate is None or convert_rate > 0, "Sample rate to convert to must be a positive integer"
        assert convert_width is None or (
            convert_width % 1 == 0 and 2 <= convert_width <= 4
        ), "Sample width to convert to must be 2, 3, or 4"

        raw_data = self.frame_data

        # resample audio at the desired rate if specified
        if convert_rate is not None and self.sample_rate != convert_rate:
            raw_data, _ = audioop.ratecv(raw_data, self.sample_width, 1,
                                         self.sample_rate, convert_rate, None)

        # convert samples to desired byte format if specified
        if convert_width is not None and self.sample_width != convert_width:
            raw_data = audioop.lin2lin(raw_data, self.sample_width,
                                       convert_width)

        return raw_data
Пример #14
0
 def normalize(self) -> 'Sample':
     """
     Normalize the sample, meaning: convert it to the default samplerate, sample width and number of channels.
     When mixing samples, they should all have the same properties, and this method is ideal to make sure of that.
     """
     if self.__locked:
         raise RuntimeError("cannot modify a locked sample")
     self.resample(params.norm_samplerate)
     if self.samplewidth != params.norm_samplewidth:
         # Convert to desired sample size.
         self.__frames = audioop.lin2lin(self.__frames, self.samplewidth,
                                         params.norm_samplewidth)
         self.__samplewidth = params.norm_samplewidth
     if params.norm_nchannels not in (1, 2):
         raise ValueError(
             "norm_nchannels has invalid value, can only be 1 or 2")
     if self.nchannels == 1 and params.norm_nchannels == 2:
         # convert to stereo
         self.__frames = audioop.tostereo(self.__frames, self.samplewidth,
                                          1, 1)
         self.__nchannels = 2
     elif self.nchannels == 2 and params.norm_nchannels == 1:
         # convert to mono
         self.__frames = audioop.tomono(self.__frames, self.__samplewidth,
                                        1, 1)
         self.__nchannels = 1
     return self
Пример #15
0
def testlin2lin(data):
	# too simple: we test only the size
	for d1 in data:
		for d2 in data:
			got = len(d1)/3
			wtd = len(d2)/3
			if len(audioop.lin2lin(d1, got, wtd)) <> len(d2):
				return 0
	return 1
Пример #16
0
    def changesampwidth(self, newsampwidth):
        """
        Return frames with the given number of bytes.

        @param newsampwidth (int) new sample width of the frames. (1 for 8 bits, 2 for 16 bits, 4 for 32 bits)
        @return converted frames

        """
        return audioop.lin2lin(self.frames, self.sampwidth, newsampwidth)
Пример #17
0
 def get_32bit_frames(self, scale_amplitude=True):
     """Returns the raw sample frames scaled to 32 bits. See make_32bit method for more info."""
     if self.samplewidth == 4:
         return self.__frames
     frames = audioop.lin2lin(self.__frames, self.samplewidth, 4)
     if not scale_amplitude:
         # we need to scale back the sample amplitude to fit back into 24/16/8 bit range
         factor = 1.0/2**(8*abs(self.samplewidth-4))
         frames = audioop.mul(frames, 4, factor)
     return frames
Пример #18
0
    def get_raw_data(self, convert_rate=None, convert_width=None):
        raw_data = self.frame_data

        # make sure unsigned 8-bit audio (which uses unsigned samples) is handled like higher sample width audio (which uses signed samples)
        if self.sample_width == 1:
            raw_data = audioop.bias(
                raw_data, 1, -128
            )  # subtract 128 from every sample to make them act like signed samples

        # resample audio at the desired rate if specified
        if convert_rate is not None and self.sample_rate != convert_rate:
            raw_data, _ = audioop.ratecv(raw_data, self.sample_width, 1,
                                         self.sample_rate, convert_rate, None)

        # convert samples to desired sample width if specified
        if convert_width is not None and self.sample_width != convert_width:
            if convert_width == 3:  # we're converting the audio into 24-bit (workaround for https://bugs.python.org/issue12866)
                raw_data = audioop.lin2lin(
                    raw_data, self.sample_width, 4
                )  # convert audio into 32-bit first, which is always supported
                try:
                    audioop.bias(
                        b"", 3, 0
                    )  # test whether 24-bit audio is supported (for example, ``audioop`` in Python 3.3 and below don't support sample width 3, while Python 3.4+ do)
                except audioop.error:  # this version of audioop doesn't support 24-bit audio (probably Python 3.3 or less)
                    raw_data = b"".join(
                        raw_data[i + 1:i + 4]
                        for i in range(0, len(raw_data), 4)
                    )  # since we're in little endian, we discard the first byte from each 32-bit sample to get a 24-bit sample
                else:  # 24-bit audio fully supported, we don't need to shim anything
                    raw_data = audioop.lin2lin(raw_data, self.sample_width,
                                               convert_width)
            else:
                raw_data = audioop.lin2lin(raw_data, self.sample_width,
                                           convert_width)

        # if the output is 8-bit audio with unsigned samples, convert the samples we've been treating as signed to unsigned again
        if convert_width == 1:
            raw_data = audioop.bias(
                raw_data, 1, 128
            )  # add 128 to every sample to make them act like unsigned samples again

        return raw_data
Пример #19
0
 def get_32bit_frames(self, scale_amplitude=True):
     """Returns the raw sample frames scaled to 32 bits. See make_32bit method for more info."""
     if self.samplewidth == 4:
         return self.__frames
     frames = audioop.lin2lin(self.__frames, self.samplewidth, 4)
     if not scale_amplitude:
         # we need to scale back the sample amplitude to fit back into 24/16/8 bit range
         factor = 1.0 / 2**(8 * abs(self.samplewidth - 4))
         frames = audioop.mul(frames, 4, factor)
     return frames
Пример #20
0
    def to_sample_width(self, sampwidth):
        'Convert to a new sample width'
        if self.params.sampwidth == sampwidth: return self
        if sampwidth not in (1, 2, 3, 4):
            raise PcmValueError('Illegal sample width: %d' % sampwidth)

        return self.__class__(self.params,
                              audioop.lin2lin(self.frames,
                                              self.params.sampwidth,
                                              sampwidth),
                              sampwidth=sampwidth)
Пример #21
0
    def _convert_data(self, data: bytes, to_depth: int, to_channels: int,
                      to_rate: int, to_unsigned: bool = False) -> bytes:
        """Convert audio data."""
        out_width = to_depth // 8

        if self._from_float:
            ldata = audioop.tomono(data, self._width, 1, 0)
            rdata = audioop.tomono(data, self._width, 0, 1)
            for mono_data in [ldata, rdata]:
                float_array = array('f', mono_data)
                out_array = array('i' if self._out_depth > 16 else 'h')
                for i in float_array:
                    if i > 1.0:
                        i = 1.0
                    elif i < -1.0:
                        i = -1.0
                    out_array.append(round(i * 32767.0))
                mono_data = out_array.tobytes()
            ldata = audioop.tostereo(ldata, self._width, 1, 0)
            rdata = audioop.tostereo(rdata, self._width, 0, 1)
            data = audioop.add(ldata, rdata, self._width)

        if self._to_alaw:
            data = audioop.lin2alaw(data, self._width)

        if self._depth != to_depth:
            data = audioop.lin2lin(
                data,
                self._width,
                out_width
            )

        if self._unsigned != to_unsigned:
            data = audioop.bias(data, out_width, 128)

        # Make it stereo
        if self._channels < to_channels:
            data = audioop.tostereo(data, out_width, 1, 1)
        # Make it mono
        elif self._channels > to_channels:
            data = audioop.tomono(data, out_width, 1, 1)

        # Convert the sample rate of the data to the requested rate.
        if self._rate != to_rate and data:
            data, self._state = audioop.ratecv(
                data,
                out_width,
                to_channels,
                self._rate,
                to_rate,
                self._state,
            )

        return data
Пример #22
0
    def change_sampwidth(self, new_sampwidth):
        """Return frames with the given number of bytes.

        :param new_sampwidth: (int) new sample width of the frames.
            (1 for 8 bits, 2 for 16 bits, 4 for 32 bits)
        :returns: (str) converted frames

        """
        if new_sampwidth not in [1, 2, 4]:
            raise SampleWidthError
        return audioop.lin2lin(self._frames, self._sampwidth, new_sampwidth)
Пример #23
0
def changesampwidth(frames, sampwidth, newsampwidth):
    """
    Change the number of bytes used to encode the frames

    @param frames (string) input frames.
    @param current sampwidth (int) sample width of the frames. (1 for 8 bits, 2 for 16 bits, 4 for 32 bits)
    @param newsampwidth (int) new sample width of the frames. (1 for 8 bits, 2 for 16 bits, 4 for 32 bits)
    @return converted frames

    """
    return audioop.lin2lin(frames, sampwidth, newsampwidth)
Пример #24
0
def testlin2lin(data):
    if verbose:
        print 'lin2lin'
    # too simple: we test only the size
    for d1 in data:
        for d2 in data:
            got = len(d1)/3
            wtd = len(d2)/3
            if len(audioop.lin2lin(d1, got, wtd)) != len(d2):
                return 0
    return 1
Пример #25
0
    def change_sampwidth(self, new_sampwidth):
        """ Return frames with the given number of bytes.

        :param new_sampwidth: (int) new sample width of the frames.
            (1 for 8 bits, 2 for 16 bits, 4 for 32 bits)
        :returns: (str) converted frames

        """
        if new_sampwidth not in [1, 2, 4]:
            raise SampleWidthError
        return audioop.lin2lin(self._frames, self._sampwidth, new_sampwidth)
Пример #26
0
def testlin2lin(data):
    if verbose:
        print 'lin2lin'
    # too simple: we test only the size
    for d1 in data:
        for d2 in data:
            got = len(d1) // 3
            wtd = len(d2) // 3
            if len(audioop.lin2lin(d1, got, wtd)) != len(d2):
                return 0
    return 1
Пример #27
0
    def write(self, data: bytes) -> int:
        """Encode and writes str to an ogg file."""
        written = 0

        if self._from_24:
            data = audioop.lin2lin(data, 3, self._depth // 8)

        for data_buffer in slice_buffer(data, self.buffer_size):
            written += self._vorbis_file.write(self._encode(data_buffer))

        return written
Пример #28
0
    def get_raw_data(self, convert_rate = None, convert_width = None):
        """
            Returns a byte string representing the raw frame data for the audio represented by the ``AudioData`` instance.
            
            If ``convert_rate`` is specified and the audio sample rate is not ``convert_rate`` Hz, the resulting audio
            is resampled to match.
            
            If ``convert_width`` is specified and the audio samples are not ``convert_width`` bytes each, the resulting
            audio is converted to match. Writing these bytes directly to a file results in a valid `RAW/PCM audio file
            <https://en.wikipedia.org/wiki/Raw_audio_format>`__.
            """
        assert convert_rate is None or convert_rate > 0, "Sample rate to convert to must be a positive integer"
        assert convert_width is None or (convert_width % 1 == 0 and 1 <= convert_width <= 4), "Sample width to convert to must be between 1 and 4 inclusive"
        
        raw_data = self.frame_data
        
        # make sure unsigned 8-bit audio (which uses unsigned samples) is handled like higher sample width audio (which uses signed samples)
        if self.sample_width == 1:
            raw_data = audioop.bias(raw_data, 1, -128) # subtract 128 from every sample to make them act like signed samples
        
        # resample audio at the desired rate if specified
        if convert_rate is not None and self.sample_rate != convert_rate:
            raw_data, _ = audioop.ratecv(raw_data, self.sample_width, 1, self.sample_rate, convert_rate, None)
        
        # convert samples to desired sample width if specified
        if convert_width is not None and self.sample_width != convert_width:
            if convert_width == 3: # we're converting the audio into 24-bit (workaround for https://bugs.python.org/issue12866)
                raw_data = audioop.lin2lin(raw_data, self.sample_width, 4) # convert audio into 32-bit first, which is always supported
                try: audioop.bias(b"", 3, 0) # test whether 24-bit audio is supported (for example, ``audioop`` in Python 3.3 and below don't support sample width 3, while Python 3.4+ do)
                except audioop.error: # this version of audioop doesn't support 24-bit audio (probably Python 3.3 or less)
                    raw_data = b"".join(raw_data[i + 1:i + 4] for i in range(0, len(raw_data), 4)) # since we're in little endian, we discard the first byte from each 32-bit sample to get a 24-bit sample
                else: # 24-bit audio fully supported, we don't need to shim anything
                    raw_data = audioop.lin2lin(raw_data, self.sample_width, convert_width)
            else:
                raw_data = audioop.lin2lin(raw_data, self.sample_width, convert_width)
        
        # if the output is 8-bit audio with unsigned samples, convert the samples we've been treating as signed to unsigned again
        if convert_width == 1:
            raw_data = audioop.bias(raw_data, 1, 128) # add 128 to every sample to make them act like unsigned samples again

        return raw_data
Пример #29
0
    def read(self, size: int = -1) -> bytes:
        """Convert audio.

        Convert the samples to the given rate and makes it mono or stereo
        depending on the channels value.
        """
        data = self._buffer

        while len(data) < size:
            temp_data = self._source.read()
            if not temp_data:
                if len(data) != 0:
                    data += b'\x00' * (size - len(data))
                break

            if self._source._floatp and not self._floatp:
                in_array = array('f', temp_data)
                out_array = array(f"{'h' if self._depth <= 16 else 'i'}")
                for i in in_array:
                    if i >= 1.0:
                        out_array.append(32767)
                    elif i <= -1.0:
                        out_array.append(-32768)
                    else:
                        out_array.append(math.floor(i * 32768.0))
                temp_data = out_array.tobytes()

            # Convert audio data from source width to self._width.
            if self._depth != self._source.depth:
                temp_data = audioop.lin2lin(temp_data, self._source._width,
                                            self._width)

            if self._unsigned != self._source.unsigned:
                temp_data = audioop.bias(temp_data, self._source._width, 128)

            # Make it stereo
            if self._source.channels < self._channels:
                temp_data = audioop.tostereo(temp_data, self._width, 1, 1)
            # Make it mono
            elif self._source.channels > self._channels:
                temp_data = audioop.tomono(temp_data, self._width, 1, 1)

            # Convert the sample rate of the data to the requested rate.
            if self._rate != self._source.rate and temp_data:
                temp_data, self._state = audioop.ratecv(
                    temp_data, self._width, self._channels, self._source.rate,
                    self._rate, self._state)

            data += temp_data

        self._buffer = data[size:]

        return data[:size]
Пример #30
0
def convert_wave_data(f_rate,frame_count,sample_width,channels,data):
    """ Convert wave sample data into pleo format
    """
    if channels==2: data = audioop.tomono(data,sample_width,1,1)
    data = audioop.mul(data,sample_width,0.97999999999999998)
    data = audioop.ratecv(data,sample_width,1,f_rate,11025,None,4,4)[0]
    if sample_width==1:
       data = audioop.bias(data,1,-128)
       data = audioop.lin2lin(data,1,2)
    data = audioop.mul(data,2,(1.0/256))
    data = audioop.lin2adpcm(data,2,None)[0]
    return (11025,frame_count,sample_width,1,data)
Пример #31
0
def rewrite():
    orign=wave.open('hass/asr20181208231910.wav')
    fms_byte=orign.readframes(orign.getnframes())
    orign.close()
    dest=wave.open('hjwavtest12.wav', 'wb')
    rebyte = audioop.lin2lin(fms_byte, 1, 2)
    cvbyte=audioop.ratecv(rebyte, 2, 1, 8000, 16000, None)[0]
    pdb.set_trace()
    dest.setnchannels(1)
    dest.setsampwidth(2)
    dest.setframerate(16000)
    dest.writeframes(cvbyte)
    dest.close()
Пример #32
0
 def _get_audio_data(self, num_bytes):
     sound = self.sequencer.tick()
     if sound is None:
         pyglet.app.exit()
         return
     self._mute(sound)
     sound = [lin2lin(s, 1, self.bytes) for s in sound]
     output = self._ratecv(sound)
     output = self._scale(output)
     output = self._tostereo(output)
     stereo = mix(output, self.bytes)
     audio = AudioData(stereo, self.audio_length, self.timestamp, self.tick_time)
     self.timestamp += self.tick_time
     return audio 
Пример #33
0
 def make_16bit(self, maximize_amplitude=True):
     """
     Convert to 16 bit sample width, usually by using a maximized amplification factor to
     scale into the full 16 bit range without clipping or overflow.
     This is used for example to downscale a 32 bits mixed sample back into 16 bit width.
     """
     assert not self.__locked
     assert self.samplewidth >= 2
     if maximize_amplitude:
         self.amplify_max()
     if self.samplewidth > 2:
         self.__frames = audioop.lin2lin(self.__frames, self.samplewidth, 2)
         self.__samplewidth = 2
     return self
Пример #34
0
 def make_16bit(self, maximize_amplitude=True):
     """
     Convert to 16 bit sample width, usually by using a maximized amplification factor to
     scale into the full 16 bit range without clipping or overflow.
     This is used for example to downscale a 32 bits mixed sample back into 16 bit width.
     """
     assert not self.__locked
     assert self.samplewidth >= 2
     if maximize_amplitude:
         self.amplify_max()
     if self.samplewidth > 2:
         self.__frames = audioop.lin2lin(self.__frames, self.samplewidth, 2)
         self.__samplewidth = 2
     return self
Пример #35
0
 def resample(self,
              data,
              freq=44100,
              bits=8,
              signed=0,
              channels=1,
              byteorder=None):
     "Convert a sample to the mixer's own format."
     bytes = bits / 8
     byteorder = byteorder or sys.byteorder
     if (freq, bytes, signed, channels, byteorder) == self.parameters:
         return data
     # convert to native endianness
     if byteorder != sys.byteorder:
         data = byteswap(data, bytes)
         byteorder = sys.byteorder
     # convert unsigned -> signed for the next operations
     if not signed:
         data = audioop.bias(data, bytes, -(1 << (bytes * 8 - 1)))
         signed = 1
     # convert stereo -> mono
     while channels > self.channels:
         assert channels % 2 == 0
         data = audioop.tomono(data, bytes, 0.5, 0.5)
         channels /= 2
     # resample to self.freq
     if freq != self.freq:
         data, ignored = audioop.ratecv(data, bytes, channels, freq,
                                        self.freq, None)
         freq = self.freq
     # convert between 8bits and 16bits
     if bytes != self.bytes:
         data = audioop.lin2lin(data, bytes, self.bytes)
         bytes = self.bytes
     # convert mono -> stereo
     while channels < self.channels:
         data = audioop.tostereo(data, bytes, 1.0, 1.0)
         channels *= 2
     # convert signed -> unsigned
     if not self.signed:
         data = audioop.bias(data, bytes, 1 << (bytes * 8 - 1))
         signed = 0
     # convert to mixer endianness
     if byteorder != self.byteorder:
         data = byteswap(data, bytes)
         byteorder = self.byteorder
     # done
     if (freq, bytes, signed, channels, byteorder) != self.parameters:
         raise ValueError, 'sound sample conversion failed'
     return data
Пример #36
0
 def calculate_max_min(self):
   self.Sound.write(".temp.wav")
   S = wave.open(".temp.wav","rb")
   Length = S.getnframes()
   BufferLen = Length / self.FragmentFactor
   Stream = S.readframes(BufferLen)
   while len(Stream) :
     Stream = audioop.lin2lin(Stream,2,1)
     Stream = audioop.tomono(Stream,1,1,-1)
     min_val, max_val = audioop.minmax(Stream, 1)
     self.Min_List.append(min_val)
     self.Max_List.append(max_val)
     Stream = S.readframes(BufferLen)
   S.close()
   os.remove(".temp.wav")
Пример #37
0
 def read(self, frames):
     data = self.obj.readframes((frames // self.channels))
     #data = data[:frames]#Hack don't know why but is returning extra frames
     if (len(data) == 0):
         raise EOFError("reached the end")
     if (self.sw != 2):
         data = audioop.lin2lin(data, self.sw, 2)
     if (self.channels == 2):
         data = audioop.tomono(data, 2, 1, 1)
     if (self.sf != 16000):
         data, self.resampler_state = audioop.ratecv(
             data, 2, 1, self.sf, 16000, self.resampler_state)
     data = data[:
                 frames]  #Hack don't know why but is returning extra frames
     return data  #returns data formatted as 48Khz 16bit mono
Пример #38
0
    def read_data(self, block_samples=1024):
        """Generates blocks of PCM data found in the file."""
        old_width = self._file.getsampwidth()

        while True:
            data = self._file.readframes(block_samples)
            if not data:
                break

            # Make sure we have the desired bitdepth and endianness.
            data = audioop.lin2lin(data, old_width, TARGET_WIDTH)
            if self._needs_byteswap and self._file.getcomptype() != 'sowt':
                # Big-endian data. Swap endianness.
                data = byteswap(data)
            yield data
Пример #39
0
    def read_data(self, block_samples=1024):
        """Generates blocks of PCM data found in the file."""
        old_width = self._file.getsampwidth()

        while True:
            data = self._file.readframes(block_samples)
            if not data:
                break

            # Make sure we have the desired bitdepth and endianness.
            data = audioop.lin2lin(data, old_width, TARGET_WIDTH)
            if self._needs_byteswap and self._file.getcomptype() != 'sowt':
                # Big-endian data. Swap endianness.
                data = byteswap(data)
            yield data
Пример #40
0
    def write(self, data: bytes) -> int:
        """Encode and writes str to an mp3 file."""
        # Scale all bit-width data above 16-bit down to 16-bit.
        if self._from_width:
            data = audioop.lin2lin(data, self._from_width, self._depth // 8)

        # Resample all audio data above 44100 down to 44100.
        if self._rate > 44100:
            data, self._state = audioop.ratecv(data, self._depth // 8,
                                               self._channels, self._rate,
                                               44100, self._state)

        # Number of samples = bytes / ((bits per sample) / 8)
        num_samples = len(data) // (self._depth // 8)
        samples_per_chan = num_samples // self._channels

        # Create a buffer to hold the encoded data.
        encoded_data = (_lame.c_ubyte * _lame.LAME_MAXMP3BUFFER)()

        data_bytes = b''

        # Split the data into samples.
        if self._depth == 16:
            # Two bytes per sample.
            data_bytes = array('h', data)
        elif self._depth == 8:
            # One byte per sample.
            data_bytes = array('b', data)

        # in_buffer_l = (_lame.c_short * samples_per_chan)(*data_bytes[::2])
        # in_buffer_r = (_lame.c_short * samples_per_chan)(*data_bytes[1::2])
        # bytes_encoded = _lame.lame_encode_buffer(self._global_flags,
        #                                             in_buffer_l,
        #                                             in_buffer_r,
        #                                             samples_per_chan,
        #                                             encoded_data,
        #                                             0)

        in_buffer = (_lame.c_short * num_samples)(*data_bytes)
        bytes_encoded = _lame.lame_encode_buffer_interleaved(
            self._global_flags, in_buffer, samples_per_chan, encoded_data,
            _lame.sizeof(encoded_data))

        # Retrieve the encoded audio data from buffer.
        out_data = _lame.string_at(encoded_data, bytes_encoded)

        # Write data to the file.
        return self._out_file.write(out_data)
Пример #41
0
 def normalize(self):
     """
     Normalize the sample, meaning: convert it to the default samplerate, sample width and number of channels.
     When mixing samples, they should all have the same properties, and this method is ideal to make sure of that.
     """
     assert not self.__locked
     self.resample(self.norm_samplerate)
     if self.samplewidth != self.norm_samplewidth:
         # Convert to 16 bit sample size.
         self.__frames = audioop.lin2lin(self.__frames, self.samplewidth, self.norm_samplewidth)
         self.__samplewidth = self.norm_samplewidth
     if self.nchannels == 1:
         # convert to stereo
         self.__frames = audioop.tostereo(self.__frames, self.samplewidth, 1, 1)
         self.__nchannels = 2
     return self
Пример #42
0
 def read_data(self):
     pa = PyAudio()
     stream = pa.open(format=paInt16,
                      channels=1,
                      rate=16000,
                      input=True,
                      frames_per_buffer=1)
     count = 0
     while True:
         if count >= 2:
             break
         print('.' + str(count))
         data = stream.read(16000)
         count += 1
         data = audioop.lin2lin(data, pa.get_sample_size(paInt16),
                                TARGET_WIDTH)
         yield data
Пример #43
0
    def read(self, size=None):
        """ Convert the samples to the given rate and makes it mono or stereo
        depending on the channels value. The data is buffered so

        """

        if not audioop:
            print("audioop not found so returning empty byte")
            return b'\x00'

        data = self._buffer

        while len(data) < size:
            temp_data = self._source.read()
            if not temp_data:
                if len(data) != 0:
                    data += b'\x00' * (size - len(data))
                break

            if self._depth != self._source.depth:
                temp_data = audioop.lin2lin(temp_data, self._source._width,
                                            self._width)

            if self._unsigned != self._source.unsigned:
                temp_data = audioop.bias(temp_data, self._source._width, 128)

            # Make it stereo
            if self._source.channels < self._channels:
                temp_data = audioop.tostereo(temp_data, self._width, 1, 1)
            # Make it mono
            elif self._source.channels > self._channels:
                temp_data = audioop.tomono(temp_data, self._width, 1, 1)

            # Convert the sample rate of the data to the requested rate.
            if self._rate != self._source.rate and temp_data:
                temp_data, self._state = audioop.ratecv(temp_data, self._width,
                                                        self._channels,
                                                        self._source.rate,
                                                        self._rate,
                                                        self._state)
            data += temp_data

        self._buffer = data[size:]

        return data[:size]
Пример #44
0
    def test_lin2lin(self):
        for w in 1, 2, 4:
            self.assertEqual(audioop.lin2lin(datas[w], w, w), datas[w])

        self.assertEqual(audioop.lin2lin(datas[1], 1, 2), packs[2](0, 0x1200, 0x4500, -0x4500, 0x7F00, -0x8000, -0x100))
        self.assertEqual(
            audioop.lin2lin(datas[1], 1, 4),
            packs[4](0, 0x12000000, 0x45000000, -0x45000000, 0x7F000000, -0x80000000, -0x1000000),
        )
        self.assertEqual(audioop.lin2lin(datas[2], 2, 1), b"\x00\x12\x45\xba\x7f\x80\xff")
        self.assertEqual(
            audioop.lin2lin(datas[2], 2, 4),
            packs[4](0, 0x12340000, 0x45670000, -0x45670000, 0x7FFF0000, -0x80000000, -0x10000),
        )
        self.assertEqual(audioop.lin2lin(datas[4], 4, 1), b"\x00\x12\x45\xba\x7f\x80\xff")
        self.assertEqual(audioop.lin2lin(datas[4], 4, 2), packs[2](0, 0x1234, 0x4567, -0x4568, 0x7FFF, -0x8000, -1))
Пример #45
0
 def get_minmax_tag(self):
     min_list = []
     max_list = []
     self.write(".temp.wav")
     Song = wave.open(".temp.wav","rb")
     NumStream = Song.getnframes()
     BufferLen = NumStream / self.FragmentFactor
     Stream = Song.readframes(BufferLen)
     while len(Stream):
         Stream = Audio.lin2lin(Stream,2,1)
         Stream = Audio.tomono(Stream,1,1,-1)
         min_val, max_val = Audio.minmax(Stream, self.ByteLength)
         min_list.append(min_val)
         max_list.append(max_val)
         Stream = Song.readframes(BufferLen)
     Song.close()
     os.remove(".temp.wav")
     return min_list, max_list
Пример #46
0
 def get_minmax_tag(self):
     min_list = []
     max_list = []
     self.write(".temp.wav")
     Song = wave.open(".temp.wav", "rb")
     NumStream = Song.getnframes()
     BufferLen = NumStream / self.FragmentFactor
     Stream = Song.readframes(BufferLen)
     while len(Stream):
         Stream = Audio.lin2lin(Stream, 2, 1)
         Stream = Audio.tomono(Stream, 1, 1, -1)
         min_val, max_val = Audio.minmax(Stream, self.ByteLength)
         min_list.append(min_val)
         max_list.append(max_val)
         Stream = Song.readframes(BufferLen)
     Song.close()
     os.remove(".temp.wav")
     return min_list, max_list
Пример #47
0
    def set_sample_width(self, sample_width):
        if sample_width == self.sample_width:
            return self

        data = self._data

        if self.sample_width == 1:
            data = audioop.bias(data, 1, -128)

        if data:
            data = audioop.lin2lin(data, self.sample_width, sample_width)
        
        if sample_width == 1:
            data = audioop.bias(data, 1, 128)

        frame_width = self.channels * sample_width
        return self._spawn(data, overrides={'sample_width': sample_width, 
                                            'frame_width': frame_width})
Пример #48
0
 def __init__(self, fp):
     self.fp = self.module.open(fp, 'rb')
     p = self.fp.getparams()
     print p
     if (p[4] not in self.allowedComp):
         raise ValueError("Incorrect file format %r"%(p,))
     self.comptype = p[4]
     if p[0] == 2:
         self._cvt = lambda x,ch=p[1],c=self._cvt: tomono(c(x),ch,0.5,0.5)
     elif p[0] != 1:
         raise ValueError("can only handle mono/stereo, not %d"%p[0])
     if p[1] != 2:
         self._cvt = lambda x,ch=p[1],c=self._cvt: lin2lin(c(x),ch,2)
     self.sampwidth = p[1]
     if p[2] % 8000 != 0:
         raise ValueError("sampfreq must be multiple of 8k")
     self.sampfreq = p[2]
     if p[2] != 8000:
         print "rate conversion"
         self._ratecvt = None
         self._cvt = lambda x,c=self._cvt: self.rateCvt(c(x))
Пример #49
0
def read_wav(filename, normalize = 0.5):
    """ Reads a wave file and return sample rate and mono audio data """
    from math import floor

    # Make header info
    sys.stderr.write('Openining : ' + filename + '\n\n')
    wf = wave.open(filename, 'rb')

    info = "\tWAV file: " + filename + "\n"
    channels = wf.getnchannels()
    info += "\tOriginal Channels: " + str(channels)
    bits = wf.getsampwidth()
    info += "\tOriginal Bits: " + str(bits*8) + "\n"
    sr = wf.getframerate()
    total_samples = wf.getnframes()
    seconds = float(total_samples)/sr
    ms_seconds = (seconds - floor(seconds)) * 1000
    info += "\tOriginal Size: " + str(total_samples*wf.getsampwidth())
    info += " Bytes ( %d" % floor(seconds)
    info += ":%05.1f" % ms_seconds
    info += ") seconds \n"
    info += "\tSample Rate: " + str(sr) + "\n"


    samples = wf.readframes(total_samples)
    wf.close()
    if bits != BITS: # It isn't 16 bits, convert to 16
        samples = audioop.lin2lin(samples, bits, BITS)
    if bits == 1 and min(samples) >= 0: # It's unsigned 8 bits
        samples = audioop.bias(samples, 2, ssc.MIN ) 

    if channels > 1:
        samples = audioop.tomono(samples, BITS, 0.75, 0.25)

    # Normalize at 50%
    maxsample = audioop.max(samples, BITS)
    samples = audioop.mul(samples, BITS, MAX * normalize / float(maxsample))

    return sr, samples, info
Пример #50
0
    def get_raw_data(self, convert_rate = None, convert_width = None):
        """
        Returns a byte string representing the raw frame data for the audio represented by the ``AudioData`` instance.

        If ``convert_rate`` is specified and the audio sample rate is not ``convert_rate`` Hz, the resulting audio is resampled to match.

        If ``convert_width`` is specified and the audio samples are not ``convert_width`` bytes each, the resulting audio is converted to match.

        Writing these bytes directly to a file results in a valid `RAW/PCM audio file <https://en.wikipedia.org/wiki/Raw_audio_format>`__.
        """
        assert convert_rate is None or convert_rate > 0, "Sample rate to convert to must be a positive integer"
        assert convert_width is None or (convert_width % 1 == 0 and 2 <= convert_width <= 4), "Sample width to convert to must be 2, 3, or 4"

        raw_data = self.frame_data

        # resample audio at the desired rate if specified
        if convert_rate is not None and self.sample_rate != convert_rate:
            raw_data, _ = audioop.ratecv(raw_data, self.sample_width, 1, self.sample_rate, convert_rate, None)

        # convert samples to desired byte format if specified
        if convert_width is not None and self.sample_width != convert_width:
            raw_data = audioop.lin2lin(raw_data, self.sample_width, convert_width)

        return raw_data
Пример #51
0
    def send_voice(self, wav, target, terminated):
        packet = bytearray()
        packet.append(self.outgoing_type.value << 5 | target.value)
        packet.extend(self._encode_varint(self.outgoing_sequence_number))

        nchannels, sampwidth, framerate, n, _, _ = wav.getparams()
        logger.debug('Sending audio: %d channels, %d-bit, %dhz, %d frames',
                     nchannels, sampwidth * 8, framerate, n)

        for i in range(n):
            pcm = wav.readframes(1)

            if sampwidth != 2:
                pcm = audioop.lin2lin(pcm, sampwidth, 2)

            if nchannels == 2:
                pcm = audioop.tomono(pcm, 2, 0.5, 0.5)

            if framerate != 48000:
                pcm, _ = audioop.ratecv(pcm, 2, 1, framerate, 48000, None)

            frame = self.outgoing_codec.encoder.encode(pcm)

            if self.outgoing_type == self.PacketType.VOICE_OPUS:
                #packet.extend(self._make_opus_header(frame))
                # TODO: figure out opus
                pass
            else:
                packet.extend(self._make_celt_header(frame, True))

                if i == n - 1 and terminated:
                    packet.extend(self._make_celt_header(b'', False))

        print(packet)
        self.transport.sendto(bytes(packet))
        self.outgoing_sequence_number += 1
Пример #52
0
    def __init__(self, filename, mode='r', depth=16, rate=44100, channels=2,
                 bigendian=False, unsigned=False, **kwargs):
        """ AllFile(self, filename, mode='r', depth=16, rate=44100, channels=2,
                    bigendian=False, unsigned=False, **kwargs) -> Loads the
        correct codec for the file and acts as a wrapper providing additional
        funcionality.

        """

        codec = get_codec(filename, blacklist=[os_basename(__file__)])

        self._supported_modes = getattr(codec, '_supported_modes', 'r')

        source = codec(filename, mode=mode, **kwargs)

        super(AllFile, self).__init__(filename, mode, source.depth,
                                      source.rate, source.channels)

        self._source = source

        self._bigendian = bigendian
        self._unsigned = unsigned

        self._state = None

        annotations = getattr(codec.read, '__annotations__')
        self.read.__annotations__.update(annotations)

        self._buffer = annotations.get('return', bytes)()
        self._buffer_size = self._source.buffer_size

        self._length = self._source.length
        self._info_dict = self._source._info_dict
        self.write = self._source.write

        self._closed = False

        if self._depth != self._source.depth:
            self._convert_depth = lambda data: \
                audioop.lin2lin(data, self._source._width, self._width)
        else:
            self._convert_depth = lambda data: data

        if self._unsigned != self._source.unsigned:
            self._convert_unsigned = lambda data: \
                audioop.bias(data, self._source._width, 128)
        else:
            self._convert_unsigned = lambda data: data

        # Make it stereo
        if self._source.channels < self._channels:
            self._convert_channels = lambda data: audioop.tostereo(data,
                                                                   self._width,
                                                                   1, 1)
        # Make it mono
        elif self._source.channels > self._channels:
            self._convert_channels = lambda data: audioop.tomono(data,
                                                                 self._width,
                                                                 1, 1)
        else:
            self._convert_channels = lambda data: data

        # Convert the sample rate of the data to the requested rate.
        if self._rate != self._source.rate:
            self._convert_rate = lambda data: audioop.ratecv(data, self._width,
                                                             self._channels,
                                                             self._source.rate,
                                                             self._rate,
                                                             self._state)
        else:
            self._convert_rate = lambda data: (data, self._state)

        if self._bigendian != self._source.bigendian:
            self._convert_endian = swap_endian
        else:
            self._convert_endian = lambda data: data
Пример #53
0
    def test_lin2lin(self):
        for w in 1, 2, 3, 4:
            self.assertEqual(audioop.lin2lin(datas[w], w, w), datas[w])
            self.assertEqual(audioop.lin2lin(bytearray(datas[w]), w, w), datas[w])
            self.assertEqual(audioop.lin2lin(memoryview(datas[w]), w, w), datas[w])

        self.assertEqual(audioop.lin2lin(datas[1], 1, 2), packs[2](0, 0x1200, 0x4500, -0x4500, 0x7F00, -0x8000, -0x100))
        self.assertEqual(
            audioop.lin2lin(datas[1], 1, 3), packs[3](0, 0x120000, 0x450000, -0x450000, 0x7F0000, -0x800000, -0x10000)
        )
        self.assertEqual(
            audioop.lin2lin(datas[1], 1, 4),
            packs[4](0, 0x12000000, 0x45000000, -0x45000000, 0x7F000000, -0x80000000, -0x1000000),
        )
        self.assertEqual(audioop.lin2lin(datas[2], 2, 1), b"\x00\x12\x45\xba\x7f\x80\xff")
        self.assertEqual(
            audioop.lin2lin(datas[2], 2, 3), packs[3](0, 0x123400, 0x456700, -0x456700, 0x7FFF00, -0x800000, -0x100)
        )
        self.assertEqual(
            audioop.lin2lin(datas[2], 2, 4),
            packs[4](0, 0x12340000, 0x45670000, -0x45670000, 0x7FFF0000, -0x80000000, -0x10000),
        )
        self.assertEqual(audioop.lin2lin(datas[3], 3, 1), b"\x00\x12\x45\xba\x7f\x80\xff")
        self.assertEqual(audioop.lin2lin(datas[3], 3, 2), packs[2](0, 0x1234, 0x4567, -0x4568, 0x7FFF, -0x8000, -1))
        self.assertEqual(
            audioop.lin2lin(datas[3], 3, 4),
            packs[4](0, 0x12345600, 0x45678900, -0x45678900, 0x7FFFFF00, -0x80000000, -0x100),
        )
        self.assertEqual(audioop.lin2lin(datas[4], 4, 1), b"\x00\x12\x45\xba\x7f\x80\xff")
        self.assertEqual(audioop.lin2lin(datas[4], 4, 2), packs[2](0, 0x1234, 0x4567, -0x4568, 0x7FFF, -0x8000, -1))
        self.assertEqual(
            audioop.lin2lin(datas[4], 4, 3), packs[3](0, 0x123456, 0x456789, -0x45678A, 0x7FFFFF, -0x800000, -1)
        )