예제 #1
0
파일: lump.py 프로젝트: devinacker/omgifol
    def to_file(self, filename, subtype='PCM_U8'):
        """Save the sound to an audio file.

        The output format is selected based on the filename extension.
        For example, "file.wav" saves to WAV format. If the file has
        no extension, WAV format is used.
        
        See the PySoundFile documentation for possible values of 'subtype'.
        Possible values depend on the output format; if the given value is
        not supported, the format's default will be used.

        Special cases: ".lmp" saves the raw lump data, and ".raw" saves
        the raw sound data."""

        format = os.path.splitext(filename)[1][1:].upper() or 'WAV'
        if   format == 'LMP': writefile(filename, self.data)
        elif format == 'RAW': writefile(filename, self.to_raw())
        elif self.format == 3:
            if   check_format(format, subtype):  pass
            elif check_format(format, 'PCM_U8'): subtype = 'PCM_U8'
            elif check_format(format, 'PCM_S8'): subtype = 'PCM_S8'
            else: subtype = None # use default for format
        
            with SoundFile(filename, 'w', self.sample_rate, 1, subtype, format=format) as file:
                # convert to signed 16-bit (since SoundFile doesn't directly support 8-bit input)
                # the result will just be converted back in the file though
                sound = (np.frombuffer(self.to_raw(), dtype='uint8').astype('int16') - 128) << 8
                file.write(sound)
        else:
            raise TypeError("audio file export only supported for digitized sounds (format 3)")
예제 #2
0
 def __init__(self,
              file: str,
              subtype: str,
              use_limiter: bool = True,
              normalize: bool = True):
     _, file_ext = os.path.splitext(file)
     file_ext = file_ext[1:].upper()
     if not sf.check_format(file_ext):
         raise TypeError(f"{file_ext} format is not supported")
     if not sf.check_format(file_ext, subtype):
         raise TypeError(
             f"{file_ext} format does not have {subtype} subtype")
     self.file = file
     self.subtype = subtype
     self.use_limiter = use_limiter
     self.normalize = normalize
예제 #3
0
    def __init__(self,
                 output_path,
                 script_path=None,
                 audio_format='wav',
                 subtype=None,
                 scp_sep=' '):
        self.output_path = output_path
        self.script_path = script_path
        self.audio_format = audio_format
        self.scp_sep = scp_sep

        assert '.' + self.audio_format in valid_ext
        if subtype is None:
            self.subtype = sf.default_subtype(self.audio_format)
        else:
            self.subtype = subtype
            assert sf.check_format(self.audio_format, self.subtype)

        if not os.path.exists(output_path):
            os.makedirs(output_path)

        if script_path is not None:
            self.f_script = open(script_path, 'w')
        else:
            self.f_script = None
예제 #4
0
    def to_file(self, filename, subtype='PCM_U8'):
        """Save the sound to an audio file.

        The output format is selected based on the filename extension.
        For example, "file.wav" saves to WAV format. If the file has
        no extension, WAV format is used.
        
        See the PySoundFile documentation for possible values of 'subtype'.
        Possible values depend on the output format; if the given value is
        not supported, the format's default will be used.

        Special cases: ".lmp" saves the raw lump data, and ".raw" saves
        the raw sound data."""

        format = os.path.splitext(filename)[1][1:].upper() or 'WAV'
        if format == 'LMP': writefile(filename, self.data)
        elif format == 'RAW': writefile(filename, self.to_raw())
        elif self.format == 3:
            if check_format(format, subtype): pass
            elif check_format(format, 'PCM_U8'): subtype = 'PCM_U8'
            elif check_format(format, 'PCM_S8'): subtype = 'PCM_S8'
            else: subtype = None  # use default for format

            with SoundFile(filename,
                           'w',
                           self.sample_rate,
                           1,
                           subtype,
                           format=format) as file:
                # convert to signed 16-bit (since SoundFile doesn't directly support 8-bit input)
                # the result will just be converted back in the file though
                sound = (np.frombuffer(
                    self.to_raw(), dtype='uint8').astype('int16') - 128) << 8
                file.write(sound)
        else:
            raise TypeError(
                "audio file export only supported for digitized sounds (format 3)"
            )
예제 #5
0
def main():
    carrier = 'anechoic.wav'
    carrier_signal, sr = soundfile.read(carrier)

    files = [
        ('cardioid_away', ['receivers/cardioid_away.wav']),
        ('concert', ['receivers/concert.wav']),
        ('binaural', ['receivers/left_ear.wav', 'receivers/right_ear.wav']),
        ('0.02', ['room_materials/0.02.wav']),
        ('0.04', ['room_materials/0.04.wav']),
        ('0.08', ['room_materials/0.08.wav']),
        ('small', ['room_sizes/small.wav']),
        ('medium', ['room_sizes/medium.wav']),
        ('large', ['room_sizes/large.wav']),
        ('large_spaced', ['room_sizes/large_spaced.wav']),
        ('tunnel_no_scatter', ['tunnel/tunnel_near_no_scatter.wav']),
        ('tunnel', ['tunnel/tunnel_near.wav']),
        ('vault', ['vault/vault.wav']),
    ]

    if not soundfile.check_format('WAV', 'PCM_24'):
        raise RuntimeError('That format is not valid')

    def convolve_channel(channel):
        signal, _ = soundfile.read(channel)
        return scipy.signal.fftconvolve(carrier_signal, signal)

    for name, channels in files:
        convolved = numpy.transpose(
            numpy.array([convolve_channel(channel) for channel in channels],
                        dtype='float32'))
        convolved /= numpy.max(numpy.abs(convolved))
        soundfile.write('out_' + name + '.wav',
                        convolved,
                        sr,
                        subtype='PCM_24',
                        format='WAV')
예제 #6
0
def mk_reader_and_writer(sr: int,
                         format='RAW',
                         subtype='PCM_16',
                         dtype='int16',
                         channels: int = 1,
                         endian=None,
                         always_2d=False):
    """Makes a (bijective) pair of numerical arrays serializer and deserializer functions.
    A function returning bijective panel data reader and writer functions with simple interfaces (all parametrizations
    are fixed): `read(source)` and `write(source, data)`.
    The writer and reader are essentially matrix (or array) serializers and deserializers respectively,
    using the same serialization protocols as waveform (into PCM, WAV, etc.)

    Args:
        sr: Sample rate. When the serialization format handles this information (e.g. WAV format)
            the sample rate is actually written (in WAV, in the header bytes), and asserted on reads
            (that is, if you read a WAV file that doesn't have that exact sample rate in it's header, a
            WrongSampleRate error will be raised.
            When the serialization format doesn't (e.g. RAW format (a.k.a. PCM)), it is ignored both on reads and writes
        format: 'RAW', 'WAV' and others (see soundfile.available_formats() for a full list)
        subtype: 'FLOAT', 'PCM_16' and others (see soundfile.available_subtypes() for a full list)
        dtype: 'float64', 'float32', 'int32', 'int16'
        channels: Number of channels (should equal the number of columns of the data matrices that will be
            serialized -- or 1 if the data is flat)
        endian: see soundfile documentation ({'FILE', 'LITTLE', 'BIG', 'CPU'}, sometimes optional)
        always_2d: By default, reading a mono sound file will return a one-dimensional array. With always_2d=True,
            data is always returned as a two-dimensional array, even if the data has only one channel.

    Returns:
        read(k), write(k, v) functions

    >>> n_channels, dtype = 1, 'float64'
    >>> read, write = mk_reader_and_writer(sr=44100, channels=n_channels, subtype='FLOAT', format='RAW', dtype=dtype)
    >>> data = _random_matrix(n_channels=n_channels, dtype=dtype)
    >>> _test_data_write_read(data, writer=write, reader=read)

    >>> n_channels, dtype = 4, 'int16'
    >>> read, write = mk_reader_and_writer(sr=2, channels=n_channels, subtype='PCM_16', format='RAW', dtype=dtype)
    >>> data = _random_matrix(n_channels=n_channels, dtype=dtype)
    >>> _test_data_write_read(data, writer=write, reader=read)
    """
    if not sf.check_format(format, subtype, endian):
        raise WrongSerializationParams(
            f"Not a valid combo: format={format}, subtype={subtype}, endian={endian}"
        )

    subtype = subtype or sf.default_subtype(format)

    if format == 'RAW':

        def read(k):
            wf, _ = sf.read(k,
                            samplerate=sr,
                            channels=channels,
                            format=format,
                            subtype=subtype,
                            dtype=dtype,
                            endian=endian,
                            always_2d=always_2d)
            return wf
    else:

        def read(k):
            wf, sr_read = sf.read(k, dtype=dtype, always_2d=always_2d)
            if sr != sr_read:
                raise WrongSampleRate(
                    f"Sample rate was {sr_read}: Expected {sr}")
            return wf

    def write(k, v):
        return sf.write(k,
                        v,
                        samplerate=sr,
                        format=format,
                        subtype=subtype,
                        endian=endian)

    # add some attributes to the functions, for diagnosis purposes
    read.sr = sr
    read.dtype = dtype
    read.format = format
    write.sr = sr
    write.format = format
    write.subtype = subtype

    return read, write