Skip to content

Commit

Permalink
Merge pull request #55 from bmcfee/documentation-013
Browse files Browse the repository at this point in the history
Documentation 0.1.3
  • Loading branch information
bmcfee authored Mar 4, 2017
2 parents 3794606 + deb8c0e commit 4fe0385
Show file tree
Hide file tree
Showing 9 changed files with 229 additions and 158 deletions.
25 changes: 22 additions & 3 deletions docs/changes.rst
Original file line number Diff line number Diff line change
@@ -1,11 +1,30 @@
.. _changes:

Changelog
=========
Release notes
=============

v0.1.3
------

* `#40`_ `BackgroundNoise` now stores sample positions in its output history
* `#44`_ fixed a bug in reconstructing muda-output jams files
* `#47`_ removed dependency on scikit-learn
* `#48`_, `#54`_ converted unit tests from nose to py.test
* `#49`_ `TimeStretch` and `PitchShift` deformers now support multiple values
* `#52`_ added the `Union` classs

.. _#40: https://github.com/bmcfee/muda/pull/40
.. _#44: https://github.com/bmcfee/muda/pull/44
.. _#47: https://github.com/bmcfee/muda/pull/47
.. _#48: https://github.com/bmcfee/muda/pull/48
.. _#49: https://github.com/bmcfee/muda/pull/49
.. _#52: https://github.com/bmcfee/muda/pull/52
.. _#54: https://github.com/bmcfee/muda/pull/54


v0.1.2
------
This ia a minor bug-fix revision.
This is a minor bug-fix revision.

* The defaults for `LogspaceTimeStretch` have been changed to a more reasonable setting.
* Track duration is now overridden when loading audio into a jams object.
Expand Down
38 changes: 15 additions & 23 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,24 +58,18 @@

# Mock the dependencies
import six
import mock

if six.PY3:
from unittest.mock import MagicMock
else:
from mock import Mock as MagicMock
MOCK_MODULES = ['librosa',
'jsonpickle',
'soundfile',
'jams',
'numpy',
'numpy.random',
'pyrubberband',
'pandas']

class Mock(MagicMock):
@classmethod
def __getattr__(cls, name):
return Mock()


MOCK_MODULES = ['librosa', 'librosa.util', 'librosa.output',
'jsonpickle', 'soundfile', 'jams',
'numpy', 'numpy.random',
'pyrubberband', 'pandas']

sys.modules.update((mod_name, Mock()) for mod_name in MOCK_MODULES)
sys.modules.update((mod_name, mock.Mock()) for mod_name in MOCK_MODULES)

# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
Expand Down Expand Up @@ -292,10 +286,8 @@ def __getattr__(cls, name):


# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {'python': ('http://docs.python.org/2', None),
'numpy': ('http://docs.scipy.org/doc/numpy/', None),
'np': ('http://docs.scipy.org/doc/numpy/', None),
'scipy': ('http://docs.scipy.org/doc/scipy/reference/', None),
'sklearn': ('http://scikit-learn.org/stable/', None),
'librosa': ('http://bmcfee.github.io/librosa', None),
'jams': ('http://pythonhosted.org/jams', None)}
intersphinx_mapping = {'python': ('https://docs.python.org/2', None),
'numpy': ('https://docs.scipy.org/doc/numpy/', None),
'scipy': ('https://docs.scipy.org/doc/scipy/reference/', None),
'librosa': ('http://librosa.github.io/librosa', None),
'jams': ('http://jams.readthedocs.io/en/latest/', None)}
8 changes: 3 additions & 5 deletions docs/core.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,10 @@ Classes

.. autoclass:: BaseTransformer
:members:
:no-undoc-members:

.. autoclass:: Pipeline
:members:
:no-undoc-members:
:inherited-members:

.. autoclass:: Union
:members:
:no-undoc-members:
:inherited-members:

31 changes: 13 additions & 18 deletions docs/deformers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,43 +7,38 @@ Deformation reference
Utilities
---------
.. autoclass:: Bypass
:no-members:
:no-undoc-members:
:inherited-members:

Audio deformers
---------------
.. autoclass:: BackgroundNoise
:no-members:
:no-undoc-members:
:inherited-members:

.. autoclass:: DynamicRangeCompression
:no-members:
:no-undoc-members:
:inherited-members:


Time-stretch deformers
----------------------

.. autoclass:: TimeStretch
:no-members:
:no-undoc-members:
:inherited-members:

.. autoclass:: RandomTimeStretch
:no-members:
:no-undoc-members:
:inherited-members:

.. autoclass:: LogspaceTimeStretch
:no-members:
:no-undoc-members:
:inherited-members:


Pitch-shift deformers
---------------------
.. autoclass:: PitchShift
:no-members:
:no-undoc-members:
:inherited-members:

.. autoclass:: RandomPitchShift
:no-members:
:no-undoc-members:
:inherited-members:

.. autoclass:: LinearPitchShift
:no-members:
:no-undoc-members:
:inherited-members:

157 changes: 157 additions & 0 deletions docs/examples.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
.. _examples:

Example usage
=============

This section gives a quick introduction to using `muda` through example applications.

Loading data
^^^^^^^^^^^^

In `muda`, all data pertaining to a track is contained within a `jams` object.
Before processing any tracks with `muda`, the jams object must be prepared using one of
`muda.load_jam_audio` or `muda.jam_pack`. These functions prepare the `jams` object to
contain (deformed) audio and store the deformation history objects.


.. code-block:: python
>>> # Loading data from disk
>>> j_orig = muda.load_jam_audio('orig.jams', 'orig.ogg')
>>> # Ready to go!
>>> # Loading audio from disk with an existing jams
>>> j_orig = jams.load('existing_jams_file.jams')
>>> j_orig = muda.load_jam_audio(existing_jams, 'orig.ogg')
>>> # Ready to go!
>>> # Loading in-memory audio (y, sr) with an existing jams
>>> j_orig = jams.load('existing_jams_file.jams')
>>> j_orig = muda.jam_pack(existing_jams, _audio=dict(y=y, sr=sr))
>>> # Ready to go!
Applying a deformation
^^^^^^^^^^^^^^^^^^^^^^
Once the data has been prepared, we are ready to start applying deformations.
This example uses a simple linear pitch shift deformer to generate five perturbations of
an input. Each deformed example is then saved to disk.

.. code-block:: python
>>> pitch = muda.deformers.LinearPitchShift(n_samples=5, lower=-1, upper=1)
>>> for i, jam_out in enumerate(pitch.transform(j_orig)):
... muda.save('output_{:02d}.ogg'.format(i),
... 'output_{:02d}.jams'.format(i),
... jam_out)
The deformed audio data can be accessed directly in the dictionary
``jam_out.sandbox.muda._audio``. Note that a full history of applied transformations
is recorded within ``jam_out.sandbox.muda`` under the ``state`` and ``history`` objects.

Pipelines
^^^^^^^^^

The following example constructs a two-stage deformation pipeline. The first stage
applies random pitch shifts, while the second stage applies random time stretches.
The pipeline therefore generates 25 examples from the input `j_orig`.

.. code-block:: python
>>> # Load an example audio file with annotation
>>> j_orig = muda.load_jam_audio('orig.jams', 'orig.ogg')
>>> # Construct a deformation pipeline
>>> pitch_shift = muda.deformers.RandomPitchShift(n_samples=5)
>>> time_stretch = muda.deformers.RandomTimeStretch(n_samples=5)
>>> pipeline = muda.Pipeline(steps=[('pitch_shift', pitch_shift),
... ('time_stretch', time_stretch)])
>>> for j_new in pipeline.transform(j_orig):
... process(j_new)
Unions
^^^^^^

`Union` operators are similar to `Pipelines`, in that they allow multiple deformers to be
combined as a single object that generates a sequence of deformations.
The difference between `Union` and `Pipeline` is that a pipeline composes deformations
together, so that a single output is the result of multiple stages of processing;
a union only applies one deformation at a time to produce a single output.

The following example is similar to the pipeline example above:

.. code-block:: python
>>> # Load an example audio file with annotation
>>> j_orig = muda.load_jam_audio('orig.jams', 'orig.ogg')
>>> # Construct a deformation pipeline
>>> pitch_shift = muda.deformers.RandomPitchShift(n_samples=5)
>>> time_stretch = muda.deformers.RandomTimeStretch(n_samples=5)
>>> union = muda.Union(steps=[('pitch_shift', pitch_shift),
... ('time_stretch', time_stretch)])
>>> for j_new in union.transform(j_orig):
... process(j_new)
Each of the resulting `j_new` objects produced by the `union` has had either
its pitch shifted by the `pitch_shift` object or its time stretched by the
`time_stretch` object, but not both.

Unions apply deformations in a round-robin schedule, so that the first output
is produced by the first deformer, the second output is produced by the second
deformer, and so on, until the list of deformers is exhausted and the first deformer
produces its second output.


Bypass operators
^^^^^^^^^^^^^^^^
When using pipelines, it is sometimes beneficial to allow a stage to be skipped, so that
the input to one stage can be fed through to the next stage without intermediate
processing. This is easily accomplished with `Bypass` objects, which first emit the
input unchanged, and then apply the contained deformation as usual. This is demonstrated
in the following example, which is similar to the pipeline example, except that it
guarantees that each stage is applied to `j_orig` in isolation, as well as in
composition. It therefore generates 36 examples (including `j_orig` itself as the first
output).

.. code-block:: python
>>> # Load an example audio file with annotation
>>> j_orig = muda.load_jam_audio('orig.jams', 'orig.ogg')
>>> # Construct a deformation pipeline
>>> pitch_shift = muda.deformers.RandomPitchShift(n_samples=5)
>>> time_stretch = muda.deformers.RandomTimeStretch(n_samples=5)
>>> pipeline = muda.Pipeline(steps=[('pitch_shift', muda.deformers.Bypass(pitch_shift)),
... ('time_stretch', muda.deformers.Bypass(time_stretch))])
>>> for j_new in pipeline.transform(j_orig):
... process(j_new)
Saving deformations
^^^^^^^^^^^^^^^^^^^
All deformation objects, including bypasses and pipelines, can be serialized to
plain-text (JSON) format, saved to disk, and reconstructed later.
This is demonstrated in the following example.

.. code-block:: python
>>> # Encode an existing pitch shift deformation object
>>> pitch_shift = muda.deformers.RandomPitchShift(n_samples=5)
>>> ps_str = muda.serialize(pitch_shift)
>>> print(ps_str)
{"params": {"n_samples": 5, "mean": 0.0, "sigma": 1.0},
"__class__": {"py/type": "muda.deformers.pitch.RandomPitchShift"}}
>>> # Reconstruct the pitch shifter from its string encoding
>>> ps2 = muda.deserialize(ps_str)
>>> # Encode a full pipeline as a string
>>> pipe_str = muda.serialize(pipeline)
>>> # Decode the string to reconstruct a new pipeline object
>>> new_pipe = muda.deserialize(pipe_str)
>>> # Process jams with the new pipeline
>>> for j_new in new_pipe.transform(j_orig):
... process(j_new)
Loading

0 comments on commit 4fe0385

Please sign in to comment.