python-soundfile Documentation

repository·master·Indexed 21 days ago

https://github.com/bastibe/python-soundfile

An audio library providing a Python interface to libsndfile using CFFI and NumPy. It enables reading and writing sampled sound file formats (such as WAV, FLAC, OGG, and MAT) as NumPy arrays, supporting high-level read/write functions, block processing via soundfile.blocks(), and granular control through SoundFile objects.

Tokens
1.6K
Snippets
8
Records
10
Agent score
24%

What's inside python-soundfile

  1. Thread safety considerations

    master

    The soundfile module follows the thread safety guarantees of libsndfile.

    Safe:

    • Concurrently opening and reading the same file using unique per-thread handles.
    • Using different files in different threads.

    Unsafe:

    • Sharing a single reader or writer handle between multiple threads.
    • Concurrently writing to the same file from different threads.
  2. Install soundfile via pip

    master

    You can install the soundfile module and its dependencies (CFFI and NumPy) using pip. On Windows, macOS, and Linux, this will also install a current version of the libsndfile library automatically.

    If you install the source package instead of the platform-specific wheels, you must manually install libsndfile using your distribution's package manager (e.g., sudo apt install libsndfile1).

    pip install soundfile
  3. Handle errors in soundfile

    master

    The module uses standard Python exceptions for API usage errors:

    • ValueError or TypeError for incorrect arguments.

    For errors originating from the underlying libsndfile library, a LibsndfileError (a subclass of SoundFileError) is raised. You can access the internal error code and message via:

    • exception.code: The libsndfile internal error code.
    • exception.error_string: The raw libsndfile error message.
  4. Convert audio formats in-memory

    master

    You can perform format conversions entirely in memory using io.BytesIO. Note that when using io.BytesIO as a target for sf.write(), you must call .seek(0) on the buffer before reading from it.

    import io
    import soundfile as sf
    
    def ogg2wav(ogg: bytes):
        ogg_buf = io.BytesIO(ogg)
        ogg_buf.name = 'file.ogg'
        data, samplerate = sf.read(ogg_buf)
        
        wav_buf = io.BytesIO()
        wav_buf.name = 'file.wav'
        sf.write(wav_buf, data, samplerate)
        wav_buf.seek(0)  # Necessary for .read() to return all bytes
        return wav_buf.read()
  5. Control bitrate and compression for MP3

    master

    For certain formats like MP3, you can specify the bitrate_mode and compression_level.

    • bitrate_mode: can be 'VARIABLE', 'CONSTANT', or 'AVERAGE'.
    • compression_level: a float between 0 and 1 (where 1 is highest compression).
    import soundfile as sf
    
    data, samplerate = sf.read('5min_32kHz.wav')
    
    # High compression VBR
    sf.write('max_compression_vbr.mp3', data, samplerate, bitrate_mode='VARIABLE', compression_level=.99)
    
    # High compression CBR
    sf.write('max_compression_cbr.mp3', data, samplerate, bitrate_mode='CONSTANT', compression_level=.99)
    
    # Minimum compression
    sf.write('min_compression_vbr.mp3', data, samplerate, bitrate_mode='VARIABLE', compression_level=0)
  6. Read RAW audio files

    master

    Since RAW files lack headers, soundfile.read() cannot auto-detect their format. You must explicitly provide the number of channels, sample rate, and subtype.

    import soundfile as sf
    
    # Reading a RAW file
    data, samplerate = sf.read('myfile.raw', channels=1, samplerate=44100, subtype='FLOAT')
  7. Read from file-like objects and Virtual IO

    master

    The soundfile.read() function supports file-like objects (e.g., io.BytesIO or objects returned by urllib.request.urlopen). This allows you to process audio data directly from memory or network streams without writing to disk.

    import io
    import soundfile as sf
    from urllib.request import urlopen
    
    # Read from a URL
    url = "http://tinyurl.com/shepard-risset"
    data, samplerate = sf.read(io.BytesIO(urlopen(url).read()))
  8. Manage files using SoundFile objects

    master

    For more granular control, you can open files as SoundFile objects. These objects maintain a file handle and allow for seeking and manual reading/writing. It is recommended to use them as context managers to ensure the file is closed properly.

    All data access uses frames as the index. A frame represents one discrete time-step and contains as many samples as there are channels.

    import soundfile as sf
    
    # Using a context manager for safe file handling
    with sf.SoundFile('myfile.wav', 'r+') as f:
        while f.tell() < f.frames:
            pos = f.tell()
            data = f.read(1024)
            f.seek(pos)
            f.write(data*2)
  9. Process audio in blocks with soundfile.blocks()

    master

    For large files, you can read audio in short, optionally overlapping blocks using soundfile.blocks(). This is useful for calculating metrics like RMS level without loading the entire file into memory.

    import numpy as np
    import soundfile as sf
    
    # Calculate RMS for each block
    rms = [np.sqrt(np.mean(block**2)) for block in
           sf.blocks('myfile.wav', blocksize=1024, overlap=512)]
  10. Read and write sound files with soundfile.read() and soundfile.write()

    master

    The simplest way to handle audio data is using the high-level soundfile.read() and soundfile.write() functions. These functions represent audio data as NumPy arrays. Supported formats include WAV, FLAC, OGG, and MAT, depending on your libsndfile installation.

    import soundfile as sf
    
    # Read a file
    data, samplerate = sf.read('existing_file.wav')
    
    # Write to a file
    sf.write('new_file.flac', data, samplerate)