Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
163 changes: 107 additions & 56 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,90 +1,141 @@
PySoundFile
===========

PySoundFile is an audio library based on libsndfile, CFFI and Numpy
`PySoundFile <https://github.com/bastibe/PySoundFile>`__ is an audio
library based on libsndfile, CFFI and Numpy. Full documentation is
available on `pysoundfile.readthedocs.org
<http://pysoundfile.readthedocs.org/>`__.

PySoundFile can read and write sound files. File reading/writing is
supported through `libsndfile <http://www.mega-nerd.com/libsndfile/>`__,
which is a free, cross-platform, open-source library for reading and
writing many different sampled sound file formats that runs on many
which is a free, cross-platform, open-source (LGPL) library for reading
and writing many different sampled sound file formats that runs on many
platforms including Windows, OS X, and Unix. It is accessed through
`CFFI <http://cffi.readthedocs.org/>`__, which is a foreign function
interface for Python calling C code. CFFI is supported for CPython 2.6+,
3.x and PyPy 2.0+. PySoundFile represents audio data as NumPy arrays.

| PySoundFile is BSD licensed.
| PySoundFile is BSD licensed (BSD 3-Clause License).
| (c) 2013, Bastian Bechtold

Installation
------------

On the Python side, you need to have CFFI and Numpy in order to use
PySoundFile. Additionally, You need the library libsndfile installed on
your computer. On Unix, use your package manager to install libsndfile.
Then just install PySoundFile using pip or ``python setup.py install``.

If you are running Windows, I recommend using
`WinPython <http://winpython.github.io/>`__ or some similar
distribution. This should set you up with Numpy. However, you also need
CFFI and it's dependency, PyCParser. A good place to get these are the
`Unofficial Windows Binaries for
Python <http://www.lfd.uci.edu/~gohlke/pythonlibs/>`__. Having installed
those, you can download the Windows installers for PySoundFile:
PySoundFile depends on the Python packages CFFI and Numpy, and the
system library libsndfile.

To install the Python dependencies, I recommend using the `Anaconda
<http://continuum.io/downloads#34>`__ Distribution of Python. Anaconda
provides the ``conda`` package manager, which will install all
dependencies using ``conda install cffi numpy`` (conda is also
independently available on pip).

You will also need to install `libsndfile
<http://www.mega-nerd.com/libsndfile/>`__. On Windows, libsndfile is
included in the binary installers (see below). On OS X, `homebrew
<http://www.mega-nerd.com/libsndfile/>`__ can install libsndfile using
``brew install libsndfile``. On Linux, use your distribution's package
manager, for example ``sudo apt-get install libsndfile``.

With CFFI, Numpy, and libsndfile installed, you can use `pip
<http://pip.readthedocs.org/en/latest/installing.html>`__ to install
`PySoundFile <https://pypi.python.org/pypi/PySoundFile/0.5.0>`__ with
``pip install pysoundfile`` or ``pip install pysoundfile --user`` if you
don't have administrator privileges. If you are running Windows you
should download the Windows installers for PySoundFile instead (which
also include libsndfile):

| `PySoundFile-0.5.0.win-amd64-py2.7 <https://github.com/bastibe/PySoundFile/releases/download/0.5.0/PySoundFile-0.5.0.win-amd64-py2.7.exe>`__
| `PySoundFile-0.5.0.win-amd64-py3.3 <https://github.com/bastibe/PySoundFile/releases/download/0.5.0/PySoundFile-0.5.0.win-amd64-py3.3.exe>`__
| `PySoundFile-0.5.0.win32-py2.7 <https://github.com/bastibe/PySoundFile/releases/download/0.5.0/PySoundFile-0.5.0.win32-py2.7.exe>`__
| `PySoundFile-0.5.0.win32-py3.3 <https://github.com/bastibe/PySoundFile/releases/download/0.5.0/PySoundFile-0.5.0.win32-py3.3.exe>`__

Usage
-----
Read/Write Functions
--------------------

Data can be written to the file using ``write()``, or read from the file
using ``read()``. PySoundFile can open all file formats that `libsndfile
supports <http://www.mega-nerd.com/libsndfile/#Features>`__, for example
WAV, FLAC, OGG and MAT files.

Here is an example for a program that reads a wave file and copies it
into an ogg-vorbis file:

.. code:: python

import pysoundfile as sf

data, samplerate = sf.read('existing_file.wav')
sf.write(data, 'new_file.ogg', samplerate=samplerate)

Block Processing
----------------

Each SoundFile can either open a sound file on the disk, or a file-like
object (using ``libsndfile``'s `virtual file
interface <http://www.mega-nerd.com/libsndfile/api.html#open_virtual>`__).
Every sound file has a specific samplerate, data format and a set number
of channels.
Sound files can also be read in short, optionally overlapping blocks.
For example, this calculates the signal level for each block of a long
file:

.. code:: python

You can read and write any file that
`libsndfile <http://www.mega-nerd.com/libsndfile/#Features>`__ can
open. This includes Microsoft WAV, OGG, FLAC and Matlab MAT files.
import numpy as np
import pysoundfile as sf

If a file on disk is opened, it is kept open for as long as the
SoundFile object exists and closes automatically when it goes out of
scope. Alternatively, the SoundFile object can be used as a context
manager, which closes the file when it exits.
rms = [np.sqrt(np.mean(block**2)) for block in
sf.blocks('myfile.wav', blocksize=1024, overlap=512)]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we drop overlap, it would fit into one line:

rms = [np.sqrt(np.mean(block**2)) for block in sf.blocks('myfile.wav', 1024)]

We could add "An overlap can be specified with, e.g., overlap=512".

I'm not sure if that's better, though.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer the long version, since it is easier to understand (what does 1024 mean?), and shows more features of the actual API.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK.


SoundFile Objects
-----------------

Sound files can also be opened as SoundFile objects. Every SoundFile
has a specific sample rate, data format and a set number of channels.

If a file is opened, it is kept open for as long as the SoundFile
object exists. The file closes when the object is garbage collected,
but you should use the ``close()`` method or the context manager to
close the file explicitly:

.. code:: python

import pysoundfile as sf

with sf.SoundFile('myfile.wav', 'rw') as f:
while f.tell() < len(f):
pos = f.tell()
data = f.read(1024)
f.seek(pos)
f.write(data*2)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An alternative implementation (untested):

with sf.SoundFile('myfile.wav', 'rw') as f:
    pos = 0
    while pos < len(f):
        f.seek(pos)
        data = f.read(1024)
        f.seek(pos)
        f.write(data*2)
        pos += 1024


All data access uses frames as index. A frame is one discrete time-step
in the sound file. Every frame contains as many samples as there are
channels in the file.

Read/Write Functions
~~~~~~~~~~~~~~~~~~~~
RAW Files
---------

Data can be written to the file using ``write()``, or read from the
file using ``read()``.

Here is an example for a program that reads a wave file and copies it
into an ogg-vorbis file:
Pysoundfile can usually auto-detect the file type of sound files. This
is not possible for RAW files, though. This is a useful idiom for
opening RAW files without having to provide all the format for every
file:

.. code:: python

import pysoundfile as sf
import pysoundfile as sf

data, samplerate = sf.read('existing_file.wav')
sf.write(data, 'new_file.ogg', samplerate=samplerate)
format = {'format':'RAW', 'subtype':'FLOAT', 'endian':'FILE'}
data = sf.read('myfile.raw', dtype='float32', **format)
sf.write(data, 'otherfile.raw', **format)

Virtual IO
~~~~~~~~~~
----------

If you have an open file-like object, you can use something similar to
this to decode it:
If you have an open file-like object, Pysoundfile can open it just like
regular files:

.. code:: python

from pysoundfile import SoundFile
with SoundFile('filename.flac', 'rb') as fObj:
data, samplerate = sf.read(fObj)
import pysoundfile as sf
with open('filename.flac', 'rb') as f:
data, samplerate = sf.read(f)

Here is an example using an HTTP request:

Expand All @@ -94,19 +145,19 @@ Here is an example using an HTTP request:
import pysoundfile as sf
import requests

fObj = BytesIO()
f = BytesIO()
response = requests.get('http://www.example.com/my.flac', stream=True)
for data in response.iter_content(4096):
if data:
fObj.write(data)
fObj.seek(0)
data, samplerate = sf.read(fObj)
f.write(data)
f.seek(0)
data, samplerate = sf.read(f)

Accessing Text Data
~~~~~~~~~~~~~~~~~~~
Accessing File Metadata
-----------------------

In addition to audio data, there are a number of text fields in every
sound file. In particular, you can set a title, a copyright notice, a
In addition to audio data, there are a number of text fields in some
sound files. In particular, you can set a title, a copyright notice, a
software description, the artist name, a comment, a date, the album
name, a license, a tracknumber and a genre. Note however, that not all
of these fields are supported for every file format.
name, a license, a track number and a genre. Note however, that not
all of these fields are supported for every file format.
4 changes: 2 additions & 2 deletions pysoundfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
To read a sound file in a block-wise fashion, use :func:`blocks`.
Alternatively, sound files can be opened as :class:`SoundFile` objects.

For further information, see http://pysoundfile.rtfd.org/.
For further information, see http://pysoundfile.readthedocs.org/.

"""
__version__ = "0.5.0"
Expand Down Expand Up @@ -521,7 +521,7 @@ class SoundFile(object):
"""A sound file.

For more documentation see the __init__() docstring (which is also
used for the online documentation (http://pysoundfile.rtfd.org/).
used for the online documentation (http://pysoundfile.readthedocs.org/).

"""

Expand Down