Skip to content

Commit

Permalink
Begin documenting the soundfile module
Browse files Browse the repository at this point in the history
  • Loading branch information
JohnVinyard committed Sep 2, 2017
1 parent 0a57b75 commit a6dbc12
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ API documentation
:maxdepth: 2

timeseries
soundfile
spectral
core

Expand Down
10 changes: 10 additions & 0 deletions docs/source/soundfile.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Soundfile
=========
.. automodule:: zounds.soundfile
.. currentmodule:: zounds.soundfile

.. autoclass:: AudioStream

.. autoclass:: Resampler

.. autoclass:: OggVorbis
5 changes: 5 additions & 0 deletions zounds/soundfile/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
"""
The soundfile module introduces :class:`featureflow.Node` subclasses that know
how to process low-level audio samples and common audio encodings.
"""

from audio_metadata import MetaData, AudioMetaDataEncoder, FreesoundOrgConfig

from ogg_vorbis import \
Expand Down
48 changes: 48 additions & 0 deletions zounds/soundfile/audiostream.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,54 @@


class AudioStream(Node):
"""
`AudioStream` expects to process a raw stream of bytes (e.g. one
produced by :class:`featureflow.ByteStream`) and produces chunks of
:class:`~zounds.timeseries.AudioSamples`
Args:
sum_to_mono (bool): True if this node should return a
:class:`~zounds.timeseries.AudioSamples` instance with a single
channel
needs (Feature): a processing node that produces a byte stream (e.g.
:class:`~featureflow.ByteStream`
Here's how'd you typically see :class:`AudioStream` used in a processing
graph.
.. code:: python
import featureflow as ff
import zounds
@zounds.simple_in_memory_settings
class Document(ff.BaseModel):
meta = ff.JSONFeature(
zounds.MetaData,
store=True,
encoder=zounds.AudioMetaDataEncoder)
raw = ff.ByteStreamFeature(
ff.ByteStream,
chunksize=2 * 44100 * 30 * 2,
needs=meta,
store=False)
pcm = zounds.AudioSamplesFeature(
zounds.AudioStream,
needs=raw,
store=True)
synth = zounds.NoiseSynthesizer(zounds.SR11025())
samples = synth.synthesize(zounds.Seconds(10))
raw_bytes = samples.encode()
_id = Document.process(meta=raw_bytes)
doc = Document(_id)
print doc.pcm.__class__ # returns an AudioSamples instance
"""

def __init__(
self,
sum_to_mono=True,
Expand Down
54 changes: 54 additions & 0 deletions zounds/soundfile/resample.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,60 @@ def __call__(self, insamples, end_of_input=False):


class Resampler(Node):
"""
`Resampler` expects to process :class:`~zounds.timeseries.AudioSamples`
instances (e.g., those produced by a :class:`AudioStream` node), and will
produce a new stream of :class:`AudioSamples` at a new sampling rate.
Args:
samplerate (AudioSampleRate): the desired sampling rate. If none is
provided, the default is :class:`~zounds.timeseries.SR44100`
needs (Feature): a processing node that produces
:class:`~zounds.timeseries.AudioSamples`
Here's how you'd typically see :class:`Resampler` used in a processing
graph.
.. code:: python
import featureflow as ff
import zounds
@zounds.simple_in_memory_settings
class Document(ff.BaseModel):
meta = ff.JSONFeature(
zounds.MetaData,
store=True,
encoder=zounds.AudioMetaDataEncoder)
raw = ff.ByteStreamFeature(
ff.ByteStream,
chunksize=2 * 44100 * 30 * 2,
needs=meta,
store=False)
pcm = zounds.AudioSamplesFeature(
zounds.AudioStream,
needs=raw,
store=True)
resampled = zounds.AudioSamplesFeature(
zounds.Resampler,
samplerate=zounds.SR22050(),
needs=pcm,
store=True)
synth = zounds.NoiseSynthesizer(zounds.SR11025())
samples = synth.synthesize(zounds.Seconds(10))
raw_bytes = samples.encode()
_id = Document.process(meta=raw_bytes)
doc = Document(_id)
print doc.pcm.samplerate.__class__.__name__ # SR11025
print doc.resampled.samplerate.__class__.__name__ # SR22050
"""
def __init__(self, samplerate=None, needs=None):
super(Resampler, self).__init__(needs=needs)
self._samplerate = samplerate or SR44100()
Expand Down

0 comments on commit a6dbc12

Please sign in to comment.