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
Beispiel #2
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
Beispiel #3
0
 def test_bias(self):
     # Note: this test assumes that avg() works
     d1 = audioop.bias(data[0], 1, 100)
     d2 = audioop.bias(data[1], 2, 100)
     d4 = audioop.bias(data[2], 4, 100)
     self.assertEqual(audioop.avg(d1, 1), 101)
     self.assertEqual(audioop.avg(d2, 2), 101)
     self.assertEqual(audioop.avg(d4, 4), 101)
def testbias(data):
	# Note: this test assumes that avg() works
	d1 = audioop.bias(data[0], 1, 100)
	d2 = audioop.bias(data[1], 2, 100)
	d4 = audioop.bias(data[2], 4, 100)
	if audioop.avg(d1, 1) <> 101 or \
		  audioop.avg(d2, 2) <> 101 or \
		  audioop.avg(d4, 4) <> 101:
		return 0
	return 1
def testbias(data):
    if verbose:
        print 'bias'
    # Note: this test assumes that avg() works
    d1 = audioop.bias(data[0], 1, 100)
    d2 = audioop.bias(data[1], 2, 100)
    d4 = audioop.bias(data[2], 4, 100)
    if audioop.avg(d1, 1) != 101 or \
              audioop.avg(d2, 2) != 101 or \
              audioop.avg(d4, 4) != 101:
        return 0
    return 1
 def __enter__(self):
     assert self.stream is None, "This audio source is already inside a context manager"
     try:
         # attempt to read the file as WAV
         self.audio_reader = wave.open(self.filename_or_fileobject, "rb")
         self.little_endian = True
         # RIFF WAV is a little-endian format (most ``audioop`` operations assume frames are stored in little-endian form)
     except wave.Error:
         try:
             # attempt to read the file as AIFF
             self.audio_reader = aifc.open(self.filename_or_fileobject, "rb")
             self.little_endian = False # AIFF is a big-endian format
         except aifc.Error:
             # attempt to read the file as FLAC
             if hasattr(self.filename_or_fileobject, "read"):
                 flac_data = self.filename_or_fileobject.read()
             else:
                 with open(self.filename_or_fileobject, "rb") as f: flac_data = f.read()
         
             # run the FLAC converter with the FLAC data to get the AIFF data
             flac_converter = get_flac_converter()
             process = subprocess.Popen([
                 flac_converter,
                 "--stdout", "--totally-silent", # put the resulting AIFF file in stdout, and make sure it's not mixed with any program output
                 "--decode", "--force-aiff-format", # decode the FLAC file into an AIFF file
                 "-", # the input FLAC file contents will be given in stdin
             ], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
             aiff_data, stderr = process.communicate(flac_data)
             aiff_file = io.BytesIO(aiff_data)
             try:
                 self.audio_reader = aifc.open(aiff_file, "rb")
             except aifc.Error:
                 assert False, "Audio file could not be read as WAV, AIFF, or FLAC; check if file is corrupted"
             self.little_endian = False # AIFF is a big-endian format
     assert 1 <= self.audio_reader.getnchannels() <= 2, "Audio must be mono or stereo"
     self.SAMPLE_WIDTH = self.audio_reader.getsampwidth()
                                                                         
     # 24-bit audio needs some special handling for old Python versions (workaround for https://bugs.python.org/issue12866)
     samples_24_bit_pretending_to_be_32_bit = False
     if self.SAMPLE_WIDTH == 3: # 24-bit audio
         try: audioop.bias(b"", self.SAMPLE_WIDTH, 0) # test whether this sample width 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)
             samples_24_bit_pretending_to_be_32_bit = True # while the ``AudioFile`` instance will outwardly appear to be 32-bit, it will actually internally be 24-bit
             self.SAMPLE_WIDTH = 4 # the ``AudioFile`` instance should present itself as a 32-bit stream now, since we'll be converting into 32-bit on the fly when reading
                                                                                                 
     self.SAMPLE_RATE = self.audio_reader.getframerate()
     self.CHUNK = 4096
     self.FRAME_COUNT = self.audio_reader.getnframes()
     self.DURATION = self.FRAME_COUNT / float(self.SAMPLE_RATE)
     self.stream = AudioFile.AudioFileStream(self.audio_reader, self.little_endian, samples_24_bit_pretending_to_be_32_bit)
     return self
Beispiel #7
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()
Beispiel #8
0
def get_swipe(dev='/dev/audio'):
    audio = ossaudiodev.open(dev, 'r')
    audio.setparameters(ossaudiodev.AFMT_S16_LE, 1, 44100)
    
    baselines = deque([2**15] * 4)
    bias = 0
    while 1:
        data, power = get_chunk(audio, bias)
        
        baseline = sum(baselines) / len(baselines) * THRESHOLD_FACTOR
        print power, baseline, power / (baseline or 1)
        
        chunks = []
        while power > baseline:
            print power, baseline, power / (baseline or 1), '*'
            chunks.append(data)
            data, power = get_chunk(audio, bias)

        if len(chunks) > 1:
            data = old_data + ''.join(chunks) + data
            while audioop.maxpp(data[:3000], 2) < baseline / 2:
                data = data[1000:]
            while audioop.maxpp(data[-3000:], 2) < baseline / 2:
                data = data[:-1000]
            
            return audioop.bias(data, 2, -audioop.avg(data, 2))

        old_data = data
        
        bias = -audioop.avg(data, 2)
        
        baselines.popleft()
        baselines.append(power)
Beispiel #9
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})
Beispiel #10
0
    def bias(self, value):
        """ Return frames that is the original fragment with a bias added to each sample.
        Samples wrap around in case of overflow.

        :param value: (int) the bias which will be applied to each sample.
        :returns: (str) converted frames

        """
        value = int(value)
        return audioop.bias(self._frames, self._sampwidth, value)
Beispiel #11
0
    def bias(self, biasvalue):
        """
        Return frames that is the original fragment with a bias added to each sample.
        Samples wrap around in case of overflow.

        @param biasvalue (int) the bias which will be applied to each sample.
        @return converted frames

        """
        return audioop.bias(self.frames, self.sampwidth, biasvalue)
Beispiel #12
0
    def bias(self, value):
        """Return frames that is the original fragment with a bias added to each sample.
        Samples wrap around in case of overflow.

        :param value: (int) the bias which will be applied to each sample.
        :returns: (str) converted frames

        """
        value = int(value)
        return audioop.bias(self._frames, self._sampwidth, value)
Beispiel #13
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
Beispiel #14
0
def bias(fragment, sampwidth, bias):
    """
    Return a fragment that is the original fragment with a bias added to each sample. Samples wrap around in case of overflow.

    @param fragment (string) input frames.
    @param sampwidth (int) sample width of the frames.
    @param bias (int) the bias which will be applied to each sample.
    @return converted frames

    """
    return audioop.bias(fragment, sampwidth, bias)
Beispiel #15
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
    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
Beispiel #17
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
                           })
Beispiel #18
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)
Beispiel #19
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]
Beispiel #20
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
Beispiel #21
0
 def from_file(cls, audio_file, audio_format=wave):
     ''' Read an audio file.
         :param audio_file: Path to audio file, or a file-like object
         :param audio_format: Python module to read audio data,
             one of wave, aifc, or sunau.
     '''
     with audio_format.open(audio_file, 'rb') as audio:
         params = audio.getparams()
         frames = audio.readframes(params.nframes)
         if audio_format is wave and params.sampwidth == 1:
             frames = audioop.bias(frames, 1, 0x80)
         if audio_format is not wave and sys.byteorder == 'little':
             frames = audioop.byteswap(frames, params.sampwidth)
         return cls(params, frames)
Beispiel #22
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

        # Perform the scaling and biasing
        if self.scale != 1.0:
            buf = audioop.mul(buf, self.source.raw_width(), self.scale)

        if self.bias != 0:
            buf = audioop.bias(buf, self.source.raw_width(), self.bias)

        return buf
Beispiel #23
0
def wav2au(data):
    # Very limited! Assumes a standard 8-bit mono .wav as input
    import audioop, struct
    freq, = struct.unpack("<i", data[24:28])
    data = data[44:]
    data = audioop.bias(data, 1, -128)
    data, ignored = audioop.ratecv(data, 1, 1, freq, 8000, None)
    data = audioop.lin2ulaw(data, 1)
    data = struct.pack('>4siiiii8s',
                       '.snd',                         # header
                       struct.calcsize('>4siiiii8s'),  # header size
                       len(data),                      # data size
                       1,                              # encoding
                       8000,                           # sample rate
                       1,                              # channels
                       'magic.au') + data
    return data
Beispiel #24
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]
def _interpret_wav(x, ch, nb):
    # Convert the data to a 16-bit sequence.
    if nb == 1:
        x = audioop.bias(x, nb, -128)

    if len(x) % nb != 0:
        print('length = {}'.format(len(x)), file=sys.stderr)
        print('width = {}'.format(nb), file=sys.stderr)
        raise RuntimeError('Not a whole number of frames')

    x = audioop.lin2lin(x, nb, 2)

    # Convert the data to a numpy array.
    scale = 1. / float(1 << 15)
    fmt = '<i{:d}'.format(2)
    y = scale * np.frombuffer(x, fmt).astype(np.float32)

    y = y.reshape((-1, ch)).T
    return y
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
Beispiel #27
0
def get_swipe():
    p = pyaudio.PyAudio()

    stream = p.open(format=FORMAT,
                    channels=CHANNELS,
                    rate=RATE,
                    input=True,
                    frames_per_buffer=CHUNK)

    baselines = deque([2**15] * 4)
    bias = 0
    while 1:
        data, power = get_chunk(stream, bias)

        baseline = sum(baselines) / len(baselines) * THRESHOLD_FACTOR
        print power, baseline, power / (baseline or 1)

        chunks = []
        while power > baseline:
            print power, baseline, power / (baseline or 1), '*'
            chunks.append(data)
            data, power = get_chunk(stream, bias)

        if len(chunks) > 1:
            data = old_data + ''.join(chunks) + data
            while audioop.maxpp(data[:3000], 2) < baseline / 2:
                data = data[1000:]
            while audioop.maxpp(data[-3000:], 2) < baseline / 2:
                data = data[:-1000]

            return audioop.bias(data, 2, -audioop.avg(data, 2))

        old_data = data

        bias = -audioop.avg(data, 2)

        baselines.popleft()
        baselines.append(power)
Beispiel #28
0
def get_swipe():
    p = pyaudio.PyAudio()

    stream = p.open(format = FORMAT,
                channels = CHANNELS,
                rate = RATE,
                input = True,
                frames_per_buffer = CHUNK)
    
    baselines = deque([2**15] * 4)
    bias = 0
    while 1:
        data, power = get_chunk(stream, bias)
        
        baseline = sum(baselines) / len(baselines) * THRESHOLD_FACTOR
        print power, baseline, power / (baseline or 1)
        
        chunks = []
        while power > baseline:
            print power, baseline, power / (baseline or 1), '*'
            chunks.append(data)
            data, power = get_chunk(stream, bias)

        if len(chunks) > 1:
            data = old_data + ''.join(chunks) + data
            while audioop.maxpp(data[:3000], 2) < baseline / 2:
                data = data[1000:]
            while audioop.maxpp(data[-3000:], 2) < baseline / 2:
                data = data[:-1000]
            
            return audioop.bias(data, 2, -audioop.avg(data, 2))

        old_data = data
        
        bias = -audioop.avg(data, 2)
        
        baselines.popleft()
        baselines.append(power)
Beispiel #29
0
 def test_bias(self):
     for w in 1, 2, 4:
         for bias in 0, 1, -1, 127, -128, 0x7FFFFFFF, -0x80000000:
             self.assertEqual(audioop.bias(b"", w, bias), b"")
     self.assertEqual(audioop.bias(datas[1], 1, 1), b"\x01\x13\x46\xbc\x80\x81\x00")
     self.assertEqual(audioop.bias(datas[1], 1, -1), b"\xff\x11\x44\xba\x7e\x7f\xfe")
     self.assertEqual(audioop.bias(datas[1], 1, 0x7FFFFFFF), b"\xff\x11\x44\xba\x7e\x7f\xfe")
     self.assertEqual(audioop.bias(datas[1], 1, -0x80000000), datas[1])
     self.assertEqual(audioop.bias(datas[2], 2, 1), packs[2](1, 0x1235, 0x4568, -0x4566, -0x8000, -0x7FFF, 0))
     self.assertEqual(audioop.bias(datas[2], 2, -1), packs[2](-1, 0x1233, 0x4566, -0x4568, 0x7FFE, 0x7FFF, -2))
     self.assertEqual(
         audioop.bias(datas[2], 2, 0x7FFFFFFF), packs[2](-1, 0x1233, 0x4566, -0x4568, 0x7FFE, 0x7FFF, -2)
     )
     self.assertEqual(audioop.bias(datas[2], 2, -0x80000000), datas[2])
     self.assertEqual(
         audioop.bias(datas[4], 4, 1), packs[4](1, 0x12345679, 0x456789AC, -0x456789AA, -0x80000000, -0x7FFFFFFF, 0)
     )
     self.assertEqual(
         audioop.bias(datas[4], 4, -1), packs[4](-1, 0x12345677, 0x456789AA, -0x456789AC, 0x7FFFFFFE, 0x7FFFFFFF, -2)
     )
     self.assertEqual(
         audioop.bias(datas[4], 4, 0x7FFFFFFF),
         packs[4](0x7FFFFFFF, -0x6DCBA989, -0x3A987656, 0x3A987654, -2, -1, 0x7FFFFFFE),
     )
     self.assertEqual(
         audioop.bias(datas[4], 4, -0x80000000),
         packs[4](-0x80000000, -0x6DCBA988, -0x3A987655, 0x3A987655, -1, 0, 0x7FFFFFFF),
     )
Beispiel #30
0
def generate_mouth_data(sample_data, compression, sample_rate, encoding):
    assert compression in constants.PCM_FORMATS
    assert encoding in constants.channel_counts
    assert sample_rate > 0

    sample_width = constants.sample_widths[compression]
    channel_count = constants.channel_counts[encoding]

    if compression == constants.COMPRESSION_PCM_8_UNSIGNED:
        # bias by 128 to shift unsigned into signed
        sample_data = audioop.bias(sample_data, 1, 128)
    elif sample_width > 1 and compression not in constants.NATIVE_ENDIANNESS_FORMATS:
        # byteswap samples to system endianness before processing
        sample_data = audioop.byteswap(sample_data, sample_width)

    if sample_width == 2:
        sample_data = memoryview(sample_data).cast("h")
    elif sample_width == 4:
        sample_data = memoryview(sample_data).cast("i")

    # mouth data is sampled at 30Hz, so we divide the audio
    # sample_rate by that to determine how many samples we must
    # consider for each fragment. also, since mouth data doesn't
    # use multiple channels, and the audio samples are interleaved,
    # we multiply the channel count into the fragment_width.
    samples_per_mouth_sample = sample_rate / constants.SAMPLE_RATE_MOUTH_DATA
    fragment_width = int(channel_count * samples_per_mouth_sample + 0.5)

    # add fragment_width - 1 to round up to next multiple of fragment_width
    fragment_count = (len(sample_data) + fragment_width - 1) // fragment_width

    # used to scale the max fragment to the [0, 255] scale of a uint8
    scale_to_uint8 = 255 / ((1 << (sample_width * 8 - 1)) - 1)

    # generate mouth data samples
    mouth_data = bytearray(fragment_count)
    for i in range(fragment_count):
        fragment = sample_data[i * fragment_width:(i + 1) * fragment_width]
        fragment_avg = sum(map(abs, fragment)) / samples_per_mouth_sample

        mouth_sample = fragment_avg * scale_to_uint8
        if mouth_sample >= 255:
            mouth_data[i] = 255
        else:
            mouth_data[i] = int(mouth_sample)

    # shift/scale the mouth samples based on the range of the mouth data
    mouth_avg = sum(mouth_data) / len(mouth_data)
    mouth_max = max(mouth_data)
    mouth_min = max(0, min(255, 2 * mouth_avg - mouth_max))

    mouth_range = (mouth_avg + mouth_max) / 2 - mouth_min
    if mouth_range == 0:
        # no range in the volume. don't try to scale
        # or shift, or else we'll divide by zero
        return bytes(mouth_data)

    for i in range(len(mouth_data)):
        mouth_sample = (mouth_data[i] - mouth_min) / mouth_range
        if mouth_sample >= 1.0:
            mouth_data[i] = 255
        elif mouth_sample <= 0.0:
            mouth_data[i] = 0
        else:
            mouth_data[i] = int(255 * mouth_sample)

    return bytes(mouth_data)
Beispiel #31
0
def convert_pcm_to_pcm(samples,
                       compression,
                       target_compression,
                       encoding=constants.ENCODING_MONO,
                       target_encoding=constants.ENCODING_MONO,
                       sample_rate=constants.SAMPLE_RATE_22K,
                       target_sample_rate=constants.SAMPLE_RATE_22K):
    '''
    Converts a stream of PCM audio to one with a different compression
    and/or encoding and/or sample rate.
    '''
    assert compression in constants.PCM_FORMATS
    assert target_compression in constants.PCM_FORMATS
    current_width = constants.sample_widths.get(compression, 1)
    target_width = constants.sample_widths.get(target_compression, 1)
    if len(samples) % current_width:
        # ensure samples are a multiple of their width
        samples = samples[:len(samples) - (len(samples) % current_width)]

    if compression == constants.COMPRESSION_PCM_8_UNSIGNED:
        # bias by 128 to shift unsigned into signed
        samples = audioop.bias(samples, 1, 128)
    elif current_width > 1 and compression not in constants.NATIVE_ENDIANNESS_FORMATS:
        # byteswap samples to system endianness before processing
        samples = audioop.byteswap(samples, current_width)
        compression = change_pcm_endianness(compression)

    if current_width != target_width:
        samples = audioop.lin2lin(samples, current_width, target_width)

        # change compression to one with the correct sample width
        compression = change_pcm_width(compression, target_width)

    # make sure to convert to/from mono/stereo
    if encoding != target_encoding:
        if (encoding == constants.ENCODING_MONO
                and target_encoding == constants.ENCODING_STEREO):
            samples = audioop.tostereo(samples, target_width, 1, 1)
        elif (encoding == constants.ENCODING_STEREO
              and target_encoding == constants.ENCODING_MONO):
            samples = audioop.tomono(samples, target_width, 0.5, 0.5)
        else:
            raise ValueError(
                "Can only convert between mono and stereo encodings.")
        encoding = target_encoding

    # convert sample rate if necessary
    if sample_rate != target_sample_rate:
        samples, _ = audioop.ratecv(samples, target_width,
                                    constants.channel_counts[encoding],
                                    sample_rate, target_sample_rate, None)
        sample_rate = target_sample_rate

    if target_compression == constants.COMPRESSION_PCM_8_UNSIGNED:
        # bias by 128 to shift signed back into unsigned
        samples = audioop.bias(samples, 1, 128)
    elif target_width > 1 and (is_big_endian_pcm(compression) !=
                               is_big_endian_pcm(target_compression)):
        # byteswap samples to target endianness
        samples = audioop.byteswap(samples, target_width)

    return samples
Beispiel #32
0
 def parsePCMA(self, packet):
     data = audioop.alaw2lin(packet.payload, 1)
     data = audioop.bias(data, 1, 128)
     self.pmin.write(packet.timestamp, data)
Beispiel #33
0
 def encodePCMA(self, packet):
     packet = audioop.bias(packet, 1, -128)
     packet = audioop.lin2alaw(packet, 1)
     return packet
Beispiel #34
0
def get_chunk(src, bias):
    data = audioop.bias(src.read(10000), 2, bias)
    return data, audioop.maxpp(data, 2)
Beispiel #35
0
def convert_audio(infile, new_rate=None, freq=None):

    global verbose

    # rSound Sample format:
    # format:2 (0)
    # wave size:2 (sample size, in pages)
    # relative pitch:2
    # stereo: 2
    # sample rate:2
    # sound data....

    if verbose: print("Input File: {}".format(infile))

    rv = bytearray()
    tr = b"\x01" + bytes(range(1, 256))  # remap 0 -> 1

    rv += struct.pack("<10x")  # header filled in later

    src, byteorder, fmt = open_audio(infile)

    width = src.getsampwidth()
    channels = src.getnchannels()
    rate = src.getframerate()
    bias = 128
    swap = width > 1 and sys.byteorder != byteorder
    if width == 1 and fmt == 'wave': bias = 0

    if verbose:
        print("Input:  {} ch, {} Hz, {}-bit, {} ({} frames)".format(
            channels, rate, width * 8, fmt, src.getnframes()))

    if channels > 2:
        raise Exception("{}: Too many channels ({})".format(infile, channels))

    cookie = None
    while True:
        frames = src.readframes(32)
        if not frames: break

        if swap:
            frames = audioop.byteswap(frames, width)

        if channels > 1:
            frames = audioop.tomono(frames, width, 0.5, 0.5)

        if new_rate:
            frames, cookie = audioop.ratecv(frames, width, 1, rate, new_rate,
                                            cookie)

        if width != 1:
            frames = audioop.lin2lin(frames, width, 1)
        if bias:
            frames = audioop.bias(frames, 1, bias)

        frames = frames.translate(tr)
        rv += frames
    src.close()

    # based on system 6 samples, pages rounds down....
    pages = (len(rv) - 10) >> 8
    hz = new_rate or rate
    rp = relative_pitch(hz, freq)

    struct.pack_into(
        "<HHHHH",
        rv,
        0,
        0,  # format
        pages,  # wave size in pages
        rp,
        0,  # stereo ???
        hz  # hz
    )

    if verbose:
        print(
            "Output: 1 ch, {} Hz, 8-bit, rSoundSample ({} frames, {:.02f} Hz)".
            format(hz,
                   len(rv) - 10, freq or 261.63))
        print()

    return rv
Beispiel #36
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
Beispiel #37
0
        bytes = s_read.getsampwidth()
        inrate = s_read.getframerate()
        print('File has ' + str(inchannels) + ' channels,' + str(bytes) +
              ' bytes per sample and rate ' + str(inrate))

        try:
            print('converting to 16KHz!')
            converted = audioop.ratecv(data, bytes, inchannels, inrate, 16000,
                                       None)
            if (inchannels == 2):
                print('converting to mono!')
                converted = audioop.tomono(converted[0], bytes, 1, 0)
            if (bytes > 1):
                print('converting to 8-bit representation!')
                converted = audioop.lin2lin(converted, bytes, 1)
                converted = audioop.bias(converted, 1, 128)
        except:
            print 'Failed to downsample wav'
            quit()

        try:
            s_read.close()
        except:
            print 'Failed to close wav file'
            quit()

        ascii = [ord(c) for c in converted]
        arrayName = fileName.partition(".")[0]
        cnt = 0

        out.write('const uint8_t ')
Beispiel #38
0
 def test_bias(self):
     for w in 1, 2, 4:
         for bias in 0, 1, -1, 127, -128, 0x7fffffff, -0x80000000:
             self.assertEqual(audioop.bias(b'', w, bias), b'')
     self.assertEqual(audioop.bias(datas[1], 1, 1),
                      b'\x01\x13\x46\xbc\x80\x81\x00')
     self.assertEqual(audioop.bias(datas[1], 1, -1),
                      b'\xff\x11\x44\xba\x7e\x7f\xfe')
     self.assertEqual(audioop.bias(datas[1], 1, 0x7fffffff),
                      b'\xff\x11\x44\xba\x7e\x7f\xfe')
     self.assertEqual(audioop.bias(datas[1], 1, -0x80000000),
                      datas[1])
     self.assertEqual(audioop.bias(datas[2], 2, 1),
             packs[2](1, 0x1235, 0x4568, -0x4566, -0x8000, -0x7fff, 0))
     self.assertEqual(audioop.bias(datas[2], 2, -1),
             packs[2](-1, 0x1233, 0x4566, -0x4568, 0x7ffe, 0x7fff, -2))
     self.assertEqual(audioop.bias(datas[2], 2, 0x7fffffff),
             packs[2](-1, 0x1233, 0x4566, -0x4568, 0x7ffe, 0x7fff, -2))
     self.assertEqual(audioop.bias(datas[2], 2, -0x80000000),
             datas[2])
     self.assertEqual(audioop.bias(datas[4], 4, 1),
             packs[4](1, 0x12345679, 0x456789ac, -0x456789aa,
                      -0x80000000, -0x7fffffff, 0))
     self.assertEqual(audioop.bias(datas[4], 4, -1),
             packs[4](-1, 0x12345677, 0x456789aa, -0x456789ac,
                      0x7ffffffe, 0x7fffffff, -2))
     self.assertEqual(audioop.bias(datas[4], 4, 0x7fffffff),
             packs[4](0x7fffffff, -0x6dcba989, -0x3a987656, 0x3a987654,
                      -2, -1, 0x7ffffffe))
     self.assertEqual(audioop.bias(datas[4], 4, -0x80000000),
             packs[4](-0x80000000, -0x6dcba988, -0x3a987655, 0x3a987655,
                      -1, 0, 0x7fffffff))
Beispiel #39
0
 def bias(self, bias: int) -> 'Sample':
     """Add a bias constant to each sample value."""
     if self.__locked:
         raise RuntimeError("cannot modify a locked sample")
     self.__frames = audioop.bias(self.__frames, self.__samplewidth, bias)
     return self
    def __enter__(self):
        #@noter:崔冰
        #@description: 读WAV/AIFF/FLAC格式的音频文件时进行的相关配置,及互相转换格式
        assert self.stream is None, "This audio source is already inside a context manager"
        try:
            # 读wav格式音频
            self.audio_reader = wave.open(self.filename_or_fileobject, "rb")
            self.little_endian = True  # WAV是小端字节序格式
        except (wave.Error, EOFError):
            try:
                # 读aiff格式音频
                self.audio_reader = aifc.open(self.filename_or_fileobject,
                                              "rb")
                self.little_endian = False  # AIFF是大端字节序格式
            except (aifc.Error, EOFError):
                # 读FLAC格式音频
                if hasattr(self.filename_or_fileobject, "read"):  #判断有无有read属性
                    flac_data = self.filename_or_fileobject.read()
                else:
                    with open(self.filename_or_fileobject, "rb") as f:
                        flac_data = f.read()

                # 运行FLAC转换器,把FLAC数据转换成AIFF数据
                flac_converter = get_flac_converter()
                if os.name == "nt":  # 在Windows中, 指定该进程将在不显示控制台窗口的情况下启动
                    startup_info = subprocess.STARTUPINFO()
                    startup_info.dwFlags |= subprocess.STARTF_USESHOWWINDOW  # 指定`startup_info`的wShowWindow字段包含一个值
                    startup_info.wShowWindow = subprocess.SW_HIDE  # 指定隐藏控制台窗口
                else:
                    startup_info = None  # 默认启动信息
                process = subprocess.Popen(
                    [
                        flac_converter,
                        "--stdout",
                        "--totally-silent",  #将生成的AIFF文件放入标准输出中,并确保它不与任何程序输出混合
                        "--decode",
                        "--force-aiff-format",  #将FLAC文件解码为AIFF 文件
                        "-",  # 输入的FLAC 文件内容将在标准输入中给出
                    ],
                    stdin=subprocess.PIPE,
                    stdout=subprocess.PIPE,
                    startupinfo=startup_info)
                aiff_data, _ = process.communicate(flac_data)
                aiff_file = io.BytesIO(aiff_data)
                try:
                    self.audio_reader = aifc.open(aiff_file, "rb")
                except (aifc.Error, EOFError):
                    raise ValueError(
                        "Audio file could not be read as PCM WAV, AIFF/AIFF-C, or Native FLAC; check if file is corrupted or in another format"
                    )
                self.little_endian = False  # AIFF是大端字节序格式
        assert 1 <= self.audio_reader.getnchannels(
        ) <= 2, "Audio must be mono or stereo"
        self.SAMPLE_WIDTH = self.audio_reader.getsampwidth()

        # 对于旧的Python版本,24位音频需要一些特殊处理 (应变方法:https://bugs.python.org/issue12866)
        samples_24_bit_pretending_to_be_32_bit = False
        if self.SAMPLE_WIDTH == 3:  # 24位音频
            try:
                audioop.bias(b"", self.SAMPLE_WIDTH, 0)  # 测试是否支持此示例宽度
            except audioop.error:  # 此版本的audioop不支持24位音频 (可能低于Python 3.3)
                samples_24_bit_pretending_to_be_32_bit = True  # 当``AudioFile`` 实例显示是 32位, 它其实是24位
                self.SAMPLE_WIDTH = 4  # “AudioFile”实例现在应该呈现为32位数据流,因为我们将在读取时转换为32位

        self.SAMPLE_RATE = self.audio_reader.getframerate()
        self.CHUNK = 4096
        self.FRAME_COUNT = self.audio_reader.getnframes()
        self.DURATION = self.FRAME_COUNT / float(self.SAMPLE_RATE)
        self.stream = AudioFile.AudioFileStream(
            self.audio_reader, self.little_endian,
            samples_24_bit_pretending_to_be_32_bit)
        return self
Beispiel #41
0
 def _flip_sign(self):
     'Flip between signed and unsigned single byte samples'
     if self.params.sampwidth != 1: return self
     return self.__class__(self.params, audioop.bias(self.frames, 1, 0x80))
Beispiel #42
0
    def __enter__(self):
        assert self.stream is None, "This audio source is already inside a context manager"
        try:
            # attempt to read the file as WAV
            self.audio_reader = wave.open(self.filename_or_fileobject, "rb")
            self.little_endian = True  # RIFF WAV is a little-endian format (most ``audioop`` operations assume that the frames are stored in little-endian form)
        except wave.Error:
            try:
                # attempt to read the file as AIFF
                self.audio_reader = aifc.open(self.filename_or_fileobject,
                                              "rb")
                self.little_endian = False  # AIFF is a big-endian format
            except aifc.Error:
                # attempt to read the file as FLAC
                if hasattr(self.filename_or_fileobject, "read"):
                    flac_data = self.filename_or_fileobject.read()
                else:
                    with open(self.filename_or_fileobject, "rb") as f:
                        flac_data = f.read()

                # run the FLAC converter with the FLAC data to get the AIFF data
                flac_converter = get_flac_converter()
                process = subprocess.Popen(
                    [
                        flac_converter,
                        "--stdout",
                        "--totally-silent",  # put the resulting AIFF file in stdout, and make sure it's not mixed with any program output
                        "--decode",
                        "--force-aiff-format",  # decode the FLAC file into an AIFF file
                        "-",  # the input FLAC file contents will be given in stdin
                    ],
                    stdin=subprocess.PIPE,
                    stdout=subprocess.PIPE)
                aiff_data, stderr = process.communicate(flac_data)
                aiff_file = io.BytesIO(aiff_data)
                try:
                    self.audio_reader = aifc.open(aiff_file, "rb")
                except aifc.Error:
                    assert False, "Audio file could not be read as WAV, AIFF, or FLAC; check if file is corrupted"
                self.little_endian = False  # AIFF is a big-endian format
        assert 1 <= self.audio_reader.getnchannels(
        ) <= 2, "Audio must be mono or stereo"
        self.SAMPLE_WIDTH = self.audio_reader.getsampwidth()

        # 24-bit audio needs some special handling for old Python versions (workaround for https://bugs.python.org/issue12866)
        samples_24_bit_pretending_to_be_32_bit = False
        if self.SAMPLE_WIDTH == 3:  # 24-bit audio
            try:
                audioop.bias(
                    b"", self.SAMPLE_WIDTH, 0
                )  # test whether this sample width 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)
                samples_24_bit_pretending_to_be_32_bit = True  # while the ``AudioFile`` instance will outwardly appear to be 32-bit, it will actually internally be 24-bit
                self.SAMPLE_WIDTH = 4  # the ``AudioFile`` instance should present itself as a 32-bit stream now, since we'll be converting into 32-bit on the fly when reading

        self.SAMPLE_RATE = self.audio_reader.getframerate()
        self.CHUNK = 4096
        self.FRAME_COUNT = self.audio_reader.getnframes()
        self.DURATION = self.FRAME_COUNT / float(self.SAMPLE_RATE)
        self.stream = AudioFile.AudioFileStream(
            self.audio_reader, self.little_endian,
            samples_24_bit_pretending_to_be_32_bit)
        return self
Beispiel #43
0
 def bias(self, bias):
     """Add a bias constant to each sample value."""
     assert not self.__locked
     self.__frames = audioop.bias(self.__frames, self.__samplewidth, bias)
     return self
Beispiel #44
0
    def iter_wave_values(self):
        """
        yield frame numer + volume value from the WAVE file
        """
        typecode = self.get_typecode(self.samplewidth)

        if log.level >= 5:
            if self.cfg.AVG_COUNT > 1:
                # merge samples -> log output in iter_avg_wave_values
                tlm = None
            else:
                tlm = TextLevelMeter(self.max_value, 79)

        # Use only a read size which is a quare divider of the samplewidth
        # Otherwise array.array will raise: ValueError: string length not a multiple of item size
        divider = int(round(float(WAVE_READ_SIZE) / self.samplewidth))
        read_size = self.samplewidth * divider
        if read_size != WAVE_READ_SIZE:
            log.info("Real use wave read size: %i Bytes" % read_size)

        get_wave_block_func = functools.partial(self.wavefile.readframes, read_size)
        skip_count = 0

        manually_audioop_bias = self.samplewidth == 1 and audioop is None

        for frames in iter(get_wave_block_func, ""):

            if self.samplewidth == 1:
                if audioop is None:
                    log.warning("use audioop.bias() work-a-round for missing audioop.")
                else:
                    # 8 bit samples are unsigned, see:
                    # http://docs.python.org/2/library/audioop.html#audioop.lin2lin
                    frames = audioop.bias(frames, 1, 128)

            try:
                values = array.array(typecode, frames)
            except ValueError, err:
                # e.g.:
                #     ValueError: string length not a multiple of item size
                # Work-a-round: Skip the last frames of this block
                frame_count = len(frames)
                divider = int(math.floor(float(frame_count) / self.samplewidth))
                new_count = self.samplewidth * divider
                frames = frames[:new_count] # skip frames
                log.error(
                    "Can't make array from %s frames: Value error: %s (Skip %i and use %i frames)" % (
                        frame_count, err, frame_count - new_count, len(frames)
                ))
                values = array.array(typecode, frames)

            for value in values:
                self.wave_pos += 1 # Absolute position in the frame stream

                if manually_audioop_bias:
                    # audioop.bias can't be used.
                    # See: http://hg.python.org/cpython/file/482590320549/Modules/audioop.c#l957
                    value = value % 0xff - 128

#                 if abs(value) < self.min_volume:
# #                     log.log(5, "Ignore to lower amplitude")
#                     skip_count += 1
#                     continue

                yield (self.wave_pos, value)
Beispiel #45
0
def get_chunk(src, bias):
    data = audioop.bias(src.read(10000), 2, bias)
    return data, audioop.maxpp(data, 2)
Beispiel #46
0
 def test_bias(self):
     for w in (1, 2, 3, 4):
         for bias in (0, 1, -1, 127, -128, 2147483647, -2147483648):
             self.assertEqual(audioop.bias(b'', w, bias), b'')
             self.assertEqual(audioop.bias(bytearray(), w, bias), b'')
             self.assertEqual(audioop.bias(memoryview(b''), w, bias), b'')
     self.assertEqual(audioop.bias(datas[1], 1, 1),
                      b'\x01\x13F\xbc\x80\x81\x00')
     self.assertEqual(audioop.bias(datas[1], 1, -1),
                      b'\xff\x11D\xba~\x7f\xfe')
     self.assertEqual(audioop.bias(datas[1], 1, 2147483647),
                      b'\xff\x11D\xba~\x7f\xfe')
     self.assertEqual(audioop.bias(datas[1], 1, -2147483648), datas[1])
     self.assertEqual(audioop.bias(datas[2], 2, 1),
                      packs[2](1, 4661, 17768, -17766, -32768, -32767, 0))
     self.assertEqual(audioop.bias(datas[2], 2, -1),
                      packs[2](-1, 4659, 17766, -17768, 32766, 32767, -2))
     self.assertEqual(audioop.bias(datas[2], 2, 2147483647),
                      packs[2](-1, 4659, 17766, -17768, 32766, 32767, -2))
     self.assertEqual(audioop.bias(datas[2], 2, -2147483648), datas[2])
     self.assertEqual(
         audioop.bias(datas[3], 3, 1),
         packs[3](1, 1193047, 4548490, -4548488, -8388608, -8388607, 0))
     self.assertEqual(
         audioop.bias(datas[3], 3, -1),
         packs[3](-1, 1193045, 4548488, -4548490, 8388606, 8388607, -2))
     self.assertEqual(
         audioop.bias(datas[3], 3, 2147483647),
         packs[3](-1, 1193045, 4548488, -4548490, 8388606, 8388607, -2))
     self.assertEqual(audioop.bias(datas[3], 3, -2147483648), datas[3])
     self.assertEqual(
         audioop.bias(datas[4], 4, 1),
         packs[4](1, 305419897, 1164413356, -1164413354, -2147483648,
                  -2147483647, 0))
     self.assertEqual(
         audioop.bias(datas[4], 4, -1),
         packs[4](-1, 305419895, 1164413354, -1164413356, 2147483646,
                  2147483647, -2))
     self.assertEqual(
         audioop.bias(datas[4], 4, 2147483647),
         packs[4](2147483647, -1842063753, -983070294, 983070292, -2, -1,
                  2147483646))
     self.assertEqual(
         audioop.bias(datas[4], 4, -2147483648),
         packs[4](-2147483648, -1842063752, -983070293, 983070293, -1, 0,
                  2147483647))
Beispiel #47
0
    def __init__(self,
                 filename: str,
                 mode: str = 'r',
                 depth: int = 16,
                 rate: int = 44100,
                 channels: int = 2,
                 bigendian: bool = False,
                 unsigned: bool = False,
                 **kwargs):
        """Loads and play all filetypes supported.

        Load 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
Beispiel #48
0
def decompose(swave,
              framerate,
              instruments=[tri_string, square_string, sin_string, saw_string]):
    matches = {}
    sample_width = 2
    total_samples = len(swave) / sample_width
    block_start = 0
    block_end = min(total_samples, block_start + BLOCK_SIZE)

    next_block = None

    while block_end - block_start == BLOCK_SIZE:
        if next_block is None:
            lblock = swave[block_start * sample_width:block_end * sample_width]
        else:
            lblock = next_block

        if DEBUG_MODE:
            debug_show_and_play_sample(lblock)

        noisy_block = False
        for j in xrange(PEAKS_IN_BLOCK):
            if next_block is None:
                peaks, phases = get_peaks_and_phases(lblock)
            else:
                peaks = next_peaks
                phases = next_phases

            if DEBUG_MODE:
                debug_display_peaks(peaks)

            peak = max(peaks)
            #TODO: normal level detection
            if peak < 1:
                print "too quiet."
                noisy_block = False
                continue
            peak_index = peaks.index(peak)
            phase = phases[peak_index]
            peaks[peak_index] = 0

            next_block = swave[block_end *
                               sample_width:(2 * block_end - block_start) *
                               sample_width]
            next_peaks, next_phases = get_peaks_and_phases(next_block)
            next_phase = next_phases[peak_index]
            phase_delta = next_phase - phase

            freq_res = float(framerate) / FFT_BLOCK_SIZE
            base_freq = (peak_index + phase_delta / (2 * math.pi)) * freq_res

            peak = 1000

            periods = int(BLOCK_SIZE * base_freq / framerate)

            wavelength = int(framerate / base_freq)
            window_left = max(0, block_start - wavelength / 2)
            window_right = min(total_samples, block_end + wavelength / 2)
            window = swave[window_left * sample_width:window_right *
                           sample_width]

            dc_offset = sum(str_to_list(window)) * sample_width / len(window)
            window = audioop.bias(window, sample_width, -dc_offset)

            best_offset = None
            best_factor = None
            best_periods = 0
            best_freq = base_freq
            best_rms = audioop.rms(window, sample_width)
            best_instrument = 0

            for p in xrange(1, periods):
                for inst, wavegen in enumerate(instruments):

                    freq = base_freq
                    pattern = wavegen(framerate, freq, peak, p)

                    offset, factor = audioop.findfit(window, pattern)
                    #window_pattern = window[offset * sample_width:offset * sample_width + len(pattern)]
                    window_pattern = window
                    pattern = complete_silence(pattern, offset,
                                               len(window) / sample_width)

                    fitted_pattern = audioop.mul(pattern, sample_width,
                                                 -factor)
                    applied_pattern = audioop.add(window_pattern,
                                                  fitted_pattern, sample_width)
                    dc_offset = sum(str_to_list(
                        applied_pattern)) * sample_width / len(applied_pattern)
                    applied_pattern = audioop.bias(applied_pattern,
                                                   sample_width, -dc_offset)

                    rms = audioop.rms(applied_pattern, sample_width)

                    # if DEBUG_MODE and p > 3:
                    # print "debug: ", p, freq, rms, best_rms, offset
                    # matplotlib.pyplot.plot(str_to_list(window_pattern), 'b')
                    # matplotlib.pyplot.plot(str_to_list(fitted_pattern), 'r')
                    # matplotlib.pyplot.plot(str_to_list(applied_pattern), 'g')

                    # matplotlib.pyplot.show()
                    # matplotlib.pyplot.close()

                    if ((best_rms > 0) and
                        (rms < best_rms * 1.02)) or (best_rms == rms == 0):
                        best_rms = rms
                        best_periods = p
                        best_factor = factor
                        best_offset = offset + window_left
                        best_instrument = inst
                        best_freq = freq

            print "found: ", best_periods, best_freq, best_rms
            if not best_freq in matches:
                matches[best_freq] = []

            if best_periods < 3:

                #block_start = max(best_offset, block_start + 1)
                #block_end = min(total_samples, block_start + BLOCK_SIZE)
                block_start = block_end
                block_end = min(total_samples, block_start + BLOCK_SIZE)
                noisy_block = True

                print "too short period"
                break

            if not best_factor:
                print "no waveforms found."
                continue
            amp = best_factor * peak
            wavegen = instruments[best_instrument]
            print "%5.2f Hz at level %5.2f for %4i periods" % (best_freq, amp,
                                                               best_periods)
            matches[best_freq].append(
                (best_offset, amp, best_periods, best_instrument))
            pattern = wavegen(framerate, best_freq, -int(amp), best_periods)
            complement = complete_silence(pattern, best_offset, total_samples)

            if DEBUG_MODE:
                waveout = wave.open("tmp.wav", "wb")
                waveout.setparams(
                    (2, 2, 44100, 531788, 'NONE', 'not compressed'))
                outdata = join_stereo(pattern, pattern)
                waveout.writeframes(outdata)
                waveout.close()
                subprocess.Popen(
                    r"C:\Program Files (x86)\Winamp\winamp.exe tmp.wav")

                matplotlib.pyplot.plot(
                    str_to_list(swave[block_start * sample_width:block_end *
                                      sample_width]))
                matplotlib.pyplot.plot(
                    str_to_list(
                        complement[block_start * sample_width:block_end *
                                   sample_width]), 'r')
                matplotlib.pyplot.show(block=True)
                matplotlib.pyplot.close()

            swave = audioop.add(swave, complement, sample_width)

        if not noisy_block:
            block_start = block_end
            block_end = min(total_samples, block_start + BLOCK_SIZE)
        print block_start, block_end
        print "block processed."

    result = audioop.mul(swave, sample_width, 0)
    for best_freq, notes in matches.iteritems():
        for note in notes:
            offset, amp, periods, best_instrument = note
            wavegen = instruments[best_instrument]
            pattern = wavegen(framerate, best_freq, amp, periods)
            prepared_sample = complete_silence(pattern, offset,
                                               len(result) / 2)
            result = audioop.add(result, prepared_sample, sample_width)
    return result
 def test_bias(self):
     for w in 1, 2, 3, 4:
         for bias in 0, 1, -1, 127, -128, 0x7fffffff, -0x80000000:
             self.assertEqual(audioop.bias(b'', w, bias), b'')
             self.assertEqual(audioop.bias(bytearray(), w, bias), b'')
             self.assertEqual(audioop.bias(memoryview(b''), w, bias), b'')
     self.assertEqual(audioop.bias(datas[1], 1, 1),
                      b'\x01\x13\x46\xbc\x80\x81\x00')
     self.assertEqual(audioop.bias(datas[1], 1, -1),
                      b'\xff\x11\x44\xba\x7e\x7f\xfe')
     self.assertEqual(audioop.bias(datas[1], 1, 0x7fffffff),
                      b'\xff\x11\x44\xba\x7e\x7f\xfe')
     self.assertEqual(audioop.bias(datas[1], 1, -0x80000000), datas[1])
     self.assertEqual(
         audioop.bias(datas[2], 2, 1), packs[2](1, 0x1235, 0x4568, -0x4566,
                                                -0x8000, -0x7fff, 0))
     self.assertEqual(
         audioop.bias(datas[2], 2, -1),
         packs[2](-1, 0x1233, 0x4566, -0x4568, 0x7ffe, 0x7fff, -2))
     self.assertEqual(
         audioop.bias(datas[2], 2, 0x7fffffff),
         packs[2](-1, 0x1233, 0x4566, -0x4568, 0x7ffe, 0x7fff, -2))
     self.assertEqual(audioop.bias(datas[2], 2, -0x80000000), datas[2])
     self.assertEqual(
         audioop.bias(datas[3], 3, 1),
         packs[3](1, 0x123457, 0x45678a, -0x456788, -0x800000, -0x7fffff,
                  0))
     self.assertEqual(
         audioop.bias(datas[3], 3, -1),
         packs[3](-1, 0x123455, 0x456788, -0x45678a, 0x7ffffe, 0x7fffff,
                  -2))
     self.assertEqual(
         audioop.bias(datas[3], 3, 0x7fffffff),
         packs[3](-1, 0x123455, 0x456788, -0x45678a, 0x7ffffe, 0x7fffff,
                  -2))
     self.assertEqual(audioop.bias(datas[3], 3, -0x80000000), datas[3])
     self.assertEqual(
         audioop.bias(datas[4], 4, 1),
         packs[4](1, 0x12345679, 0x456789ac, -0x456789aa, -0x80000000,
                  -0x7fffffff, 0))
     self.assertEqual(
         audioop.bias(datas[4], 4, -1),
         packs[4](-1, 0x12345677, 0x456789aa, -0x456789ac, 0x7ffffffe,
                  0x7fffffff, -2))
     self.assertEqual(
         audioop.bias(datas[4], 4, 0x7fffffff),
         packs[4](0x7fffffff, -0x6dcba989, -0x3a987656, 0x3a987654, -2, -1,
                  0x7ffffffe))
     self.assertEqual(
         audioop.bias(datas[4], 4, -0x80000000),
         packs[4](-0x80000000, -0x6dcba988, -0x3a987655, 0x3a987655, -1, 0,
                  0x7fffffff))
Beispiel #50
0
    def __init__(self, filename, pitch=None, rate=None, channel=0, **kwargs):

        super().__init__(**kwargs)

        new_rate = rate
        freq = pitch_to_hz(pitch)
        if not freq: raise ValueError("Invalid pitch: {}".format(pitch))

        # audio conversion

        verbose = False
        # if verbose: print("Input File: {}".format(filename))

        rv = bytearray()
        tr = b"\x01" + bytes(range(1, 256))  # remap 0 -> 1

        rv += struct.pack("<10x")  # header filled in later

        src, byteorder, fmt = open_audio(filename)

        width = src.getsampwidth()
        channels = src.getnchannels()
        rate = src.getframerate()
        bias = 128
        swap = width > 1 and sys.byteorder != byteorder
        if width == 1 and fmt == 'wave': bias = 0

        if verbose:
            print("Input:  {} ch, {} Hz, {}-bit, {} ({} frames)".format(
                channels, rate, width * 8, fmt, src.getnframes()))

        if channels > 2:
            raise Exception("{}: Too many channels ({})".format(
                filename, channels))

        cookie = None
        while True:
            frames = src.readframes(32)
            if not frames: break

            if swap:
                frames = audioop.byteswap(frames, width)

            if channels > 1:
                frames = audioop.tomono(frames, width, 0.5, 0.5)

            if new_rate:
                frames, cookie = audioop.ratecv(frames, width, 1, rate,
                                                new_rate, cookie)

            if width != 1:
                frames = audioop.lin2lin(frames, width, 1)
            if bias:
                frames = audioop.bias(frames, 1, bias)

            frames = frames.translate(tr)
            rv += frames
        src.close()

        # based on system 6 samples, pages rounds down....
        # probably a bug.
        pages = (len(rv) - 10 + 255) >> 8
        hz = new_rate or rate
        rp = relative_pitch(hz, freq)

        struct.pack_into(
            "<HHHHH",
            rv,
            0,
            0,  # format
            pages,  # wave size in pages
            rp,
            channel,  # stereo
            hz  # hz
        )

        self.data = bytes(rv)
        self.pages = pages
        self.channel = channel
        self.relative_pitch = rp
        self.sample_rate = hz

        if verbose:
            print(
                "Output: 1 ch, {} Hz, 8-bit, rSoundSample ({} frames, {:.02f} Hz)"
                .format(hz,
                        len(rv) - 10, freq or 261.63))
            print()