]> git.parisson.com Git - timeside.git/commitdiff
Refactoring: move tools to timeside.core
authorThomas Fillon <thomas@parisson.com>
Wed, 14 Jan 2015 12:16:14 +0000 (13:16 +0100)
committerThomas Fillon <thomas@parisson.com>
Wed, 14 Jan 2015 12:16:14 +0000 (13:16 +0100)
18 files changed:
timeside/core/tools/__init__.py [new file with mode: 0644]
timeside/core/tools/buffering.py [new file with mode: 0644]
timeside/core/tools/cache.py [new file with mode: 0644]
timeside/core/tools/gstutils.py [new file with mode: 0644]
timeside/core/tools/hdf5.py [new file with mode: 0644]
timeside/core/tools/logger.py [new file with mode: 0644]
timeside/core/tools/package.py [new file with mode: 0644]
timeside/core/tools/parameters.py [new file with mode: 0644]
timeside/core/tools/test_samples.py [new file with mode: 0644]
timeside/tools/__init__.py [deleted file]
timeside/tools/buffering.py [deleted file]
timeside/tools/cache.py [deleted file]
timeside/tools/gstutils.py [deleted file]
timeside/tools/hdf5.py [deleted file]
timeside/tools/logger.py [deleted file]
timeside/tools/package.py [deleted file]
timeside/tools/parameters.py [deleted file]
timeside/tools/test_samples.py [deleted file]

diff --git a/timeside/core/tools/__init__.py b/timeside/core/tools/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/timeside/core/tools/buffering.py b/timeside/core/tools/buffering.py
new file mode 100644 (file)
index 0000000..bcc4e0e
--- /dev/null
@@ -0,0 +1,79 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2014 Parisson SARL
+# Copyright (c) 2014 Thomas Fillon <thomas@parisson.com>
+
+# This file is part of TimeSide.
+
+# TimeSide is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+
+# TimeSide is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with TimeSide.  If not, see <http://www.gnu.org/licenses/>.
+#
+# Author : Thomas Fillon <thomas@parisson.com>
+
+import tables
+from tempfile import NamedTemporaryFile
+import numpy as np
+
+class BufferTable(object):
+    def __init__(self, array_names=None):
+        self._tempfile = NamedTemporaryFile(mode='w', suffix='.h5',
+                                            prefix='ts_buf_',
+                                            delete=True)
+        self.fileh = tables.openFile(self._tempfile.name, mode='w')
+
+        if not array_names:
+            array_names = []
+        if isinstance(array_names, list):
+            self.array_names = array_names
+        else:
+            self.array_names = [array_names]
+        for name in array_names:
+            if not isinstance(name, basestring):
+                raise(TypeError, 'String argument require in array_names')
+
+    def __getitem__(self, name):
+        return self.fileh.root.__getattr__(name)
+
+    #def __set_item__(self, name, value):
+    #    self.fileh.root.__setattr__(name, value)
+
+    def append(self, name, new_array):
+        try:
+            if new_array.shape:
+                self.fileh.root.__getattr__(name).append(new_array[np.newaxis,
+                                                                   :])
+            else:
+                self.fileh.root.__getattr__(name).append([new_array])
+        except tables.exceptions.NoSuchNodeError:
+            if name not in self.array_names:
+                self.array_names.append(name)
+             # The following is compatible with pytables 3 only
+             #self.fileh.create_earray(where=self.fileh.root,
+             #                         name=name,
+             #                         obj=[new_array])
+            atom = tables.Atom.from_dtype(new_array.dtype)
+            dim_list = [0]
+            dim_list.extend([dim for dim in new_array.shape])
+            shape = tuple(dim_list)
+
+            self.fileh.createEArray(where=self.fileh.root,
+                                    name=name,
+                                    atom=atom,
+                                    shape=shape)
+            self.append(name, new_array)
+
+    def close(self):
+        for name in self.array_names:
+            self.fileh.removeNode(self.fileh.root, name)
+        self.fileh.close()
+        self._tempfile.close()
diff --git a/timeside/core/tools/cache.py b/timeside/core/tools/cache.py
new file mode 100644 (file)
index 0000000..592524a
--- /dev/null
@@ -0,0 +1,118 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2006-2010 Guillaume Pellerin
+
+# <yomguy@parisson.com>
+
+# This software is a computer program whose purpose is to stream audio
+# and video data through icecast2 servers.
+
+# This software is governed by the CeCILL license under French law and
+# abiding by the rules of distribution of free software. You can use,
+# modify and/ or redistribute the software under the terms of the CeCILL
+# license as circulated by CEA, CNRS and INRIA at the following URL
+# "http://www.cecill.info".
+
+# As a counterpart to the access to the source code and  rights to copy,
+# modify and redistribute granted by the license, users are provided only
+# with a limited warranty and the software's author, the holder of the
+# economic rights, and the successive licensors have only limited
+# liability.
+
+# In this respect, the user's attention is drawn to the risks associated
+# with loading, using,  modifying and/or developing or reproducing the
+# software by the user in light of its specific status of free software,
+# that may mean that it is complicated to manipulate, and that also
+# therefore means that it is reserved for developers and  experienced
+# professionals having in-depth computer knowledge. Users are therefore
+# encouraged to load and test the software's suitability as regards their
+# requirements in conditions enabling the security of their systems and/or
+# data to be ensured and, more generally, to use and operate it in the
+# same conditions as regards security.
+
+# The fact that you are presently reading this means that you have had
+# knowledge of the CeCILL license and that you accept its terms.
+
+# Author: Guillaume Pellerin <yomguy@parisson.com>
+
+import os
+import xml.dom.minidom
+
+
+class Cache(object):
+
+    def __init__(self, dir, params=None):
+        self.dir = dir
+        self.params = params
+        self.files = self.get_files()
+
+    def get_files(self):
+        list = []
+        for root, dirs, files in os.walk(self.dir):
+            for file in files:
+                list.append(file)
+        return list
+
+    def exists(self, file):
+        self.files = self.get_files()
+        return file in self.files
+
+    def write_bin(self, data, file):
+        path = self.dir + os.sep + file
+        f = open(path, 'w')
+        f.write(data)
+        f.close()
+
+    def read_bin(self, file):
+        path = self.dir + os.sep + file
+        f = open(path, 'r')
+        data = f.read()
+        f.close()
+        return data
+
+    def read_stream_bin(self, file):
+        path = self.dir + os.sep + file
+        chunk_size = 0x1000
+        f = open(path, 'r')
+        while True:
+            _chunk = f.read(chunk_size)
+            if not len(_chunk):
+                break
+            yield _chunk
+        f.close()
+
+    def write_stream_bin(self, chunk, file_object):
+        file_object.write(chunk)
+
+    def read_analyzer_xml(self, file):
+        list = []
+        path = self.dir + os.sep + file
+        doc = xml.dom.minidom.parse(path)
+        for data in doc.documentElement.getElementsByTagName('data'):
+            name = data.getAttribute('name')
+            id = data.getAttribute('id')
+            unit = data.getAttribute('unit')
+            value = data.getAttribute('value')
+            list.append({'name': name, 'id': id, 'unit': unit, 'value': value})
+        return list
+
+    def write_analyzer_xml(self, data_list, file):
+        path = self.dir + os.sep + file
+        doc = xml.dom.minidom.Document()
+        root = doc.createElement('telemeta')
+        doc.appendChild(root)
+        for data in data_list:
+            name = data['name']
+            id = data['id']
+            unit = data['unit']
+            value = data['value']
+            node = doc.createElement('data')
+            node.setAttribute('name', name)
+            node.setAttribute('id', id)
+            node.setAttribute('unit', unit)
+            node.setAttribute('value', str(value))
+            root.appendChild(node)
+        f = open(path, "w")
+        f.write(xml.dom.minidom.Document.toprettyxml(doc))
+        f.close()
diff --git a/timeside/core/tools/gstutils.py b/timeside/core/tools/gstutils.py
new file mode 100644 (file)
index 0000000..6d06a3e
--- /dev/null
@@ -0,0 +1,35 @@
+from numpy import getbuffer, frombuffer
+
+import pygst
+pygst.require('0.10')
+import gst
+import gobject
+gobject.threads_init()
+
+import threading
+
+
+def numpy_array_to_gst_buffer(frames, chunk_size, num_samples, sample_rate):
+    from gst import Buffer
+    """ gstreamer buffer to numpy array conversion """
+    buf = Buffer(getbuffer(frames.astype("float32")))
+    # Set its timestamp and duration
+    buf.timestamp = gst.util_uint64_scale(num_samples, gst.SECOND, sample_rate)
+    buf.duration = gst.util_uint64_scale(chunk_size, gst.SECOND, sample_rate)
+    return buf
+
+
+def gst_buffer_to_numpy_array(buf, chan):
+    """ gstreamer buffer to numpy array conversion """
+    samples = frombuffer(buf.data, dtype='float32').reshape((-1, chan))
+    return samples
+
+
+class MainloopThread(threading.Thread):
+
+    def __init__(self, mainloop):
+        threading.Thread.__init__(self)
+        self.mainloop = mainloop
+
+    def run(self):
+        self.mainloop.run()
diff --git a/timeside/core/tools/hdf5.py b/timeside/core/tools/hdf5.py
new file mode 100644 (file)
index 0000000..2db446e
--- /dev/null
@@ -0,0 +1,41 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2007-2013 Parisson SARL
+
+# This file is part of TimeSide.
+
+# TimeSide is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+
+# TimeSide is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with TimeSide.  If not, see <http://www.gnu.org/licenses/>.
+
+# Author:
+#   Thomas Fillon <thomas  at parisson.com>
+
+
+def dict_to_hdf5(dict_like, h5group):
+    """
+    Save a dictionnary-like object inside a h5 file group
+    """
+    # Write attributes
+    attrs = dict_like.keys()
+    for name in attrs:
+        if dict_like[name] is not None:
+            h5group.attrs[str(name)] = dict_like[name]
+
+
+def dict_from_hdf5(dict_like, h5group):
+    """
+    Load a dictionnary-like object from a h5 file group
+    """
+    # Read attributes
+    for name, value in h5group.attrs.items():
+        dict_like[name] = value
diff --git a/timeside/core/tools/logger.py b/timeside/core/tools/logger.py
new file mode 100644 (file)
index 0000000..1405627
--- /dev/null
@@ -0,0 +1,24 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+import logging
+
+
+class Logger:
+
+    """A logging object"""
+
+    def __init__(self, file):
+        self.logger = logging.getLogger('myapp')
+        self.hdlr = logging.FileHandler(file)
+        self.formatter = logging.Formatter(
+            '%(asctime)s %(levelname)s %(message)s')
+        self.hdlr.setFormatter(self.formatter)
+        self.logger.addHandler(self.hdlr)
+        self.logger.setLevel(logging.INFO)
+
+    def write_info(self, message):
+        self.logger.info(message)
+
+    def write_error(self, message):
+        self.logger.error(message)
diff --git a/timeside/core/tools/package.py b/timeside/core/tools/package.py
new file mode 100644 (file)
index 0000000..a31b887
--- /dev/null
@@ -0,0 +1,162 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2013-2014 Thomas Fillon <thomas.fillon@parisson.com>
+
+# This file is part of TimeSide.
+
+# TimeSide is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+
+# TimeSide is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with TimeSide.  If not, see <http://www.gnu.org/licenses/>.
+
+# Author: Thomas Fillon <thomas.fillon@parisson.com>
+
+
+from importlib import import_module
+import warnings
+
+from ..core.exceptions import VampImportError
+
+def discover_modules(subpackage, package=None):
+    import pkgutil
+
+    if package:
+        try:
+            _pkg = import_module('.' + subpackage, package)
+        except ImportError as e:
+            raise e
+    else:
+        _pkg = import_module(subpackage)
+
+    pkg_path = _pkg.__path__
+    pkg_prefix = _pkg.__name__ + '.'
+
+    _list = [import_module_with_exceptions(modname)
+             for importer, modname, ispkg
+             in pkgutil.walk_packages(pkg_path, pkg_prefix)]
+
+    modules_list = [mod for mod in _list if mod is not None]
+    return modules_list
+
+
+def import_module_with_exceptions(name, package=None):
+    """Wrapper around importlib.import_module to import TimeSide subpackage
+    and ignoring ImportError if Aubio, Yaafe and Vamp Host are not available"""
+
+    from timeside.core import _WITH_AUBIO, _WITH_YAAFE, _WITH_VAMP
+
+    if name.count('.server.'):
+        # TODO:
+        # Temporary skip all timeside.server submodules before check dependencies
+        return
+    try:
+        import_module(name, package)
+    except VampImportError:
+        # No Vamp Host
+        if _WITH_VAMP:
+            raise VampImportError
+        else:
+            # Ignore Vamp ImportError
+            return
+    except ImportError as e:
+        if str(e).count('yaafelib') and not _WITH_YAAFE:
+            # Ignore Yaafe ImportError
+            return
+        elif str(e).count('aubio') and not _WITH_AUBIO:
+            # Ignore Aubio ImportError
+            return
+        elif str(e).count('DJANGO_SETTINGS_MODULE'):
+            # Ignore module requiring DJANGO_SETTINGS_MODULE in environnement
+            return
+        else:
+            print (name, package)
+            raise e
+    return name
+
+
+# Check Availability of external Audio feature extraction librairies
+def check_aubio():
+    "Check Aubio availability"
+    try:
+        import aubio
+    except ImportError:
+        warnings.warn('Aubio librairy is not available', ImportWarning,
+                      stacklevel=2)
+        _WITH_AUBIO = False
+    else:
+        _WITH_AUBIO = True
+        del aubio
+
+    return _WITH_AUBIO
+
+
+def check_yaafe():
+    "Check Aubio availability"
+    try:
+        import yaafelib
+    except ImportError:
+        warnings.warn('Yaafe librairy is not available', ImportWarning,
+                      stacklevel=2)
+        _WITH_YAAFE = False
+    else:
+        _WITH_YAAFE = True
+        del yaafelib
+    return _WITH_YAAFE
+
+
+def check_vamp():
+    "Check Vamp host availability"
+    from ..core.exceptions import VampImportError
+
+    try:
+        from timeside.plugins.analyzer.externals import vamp_plugin
+    except VampImportError:
+        warnings.warn('Vamp host is not available', ImportWarning,
+                      stacklevel=2)
+        _WITH_VAMP = False
+    else:
+        _WITH_VAMP = True
+        del vamp_plugin
+
+    return _WITH_VAMP
+
+def add_gstreamer_packages():
+    import os
+    import sys
+    from distutils.sysconfig import get_python_lib
+
+    dest_dir = get_python_lib()
+
+    packages = ['gobject', 'glib', 'pygst', 'pygst.pyc', 'pygst.pth',
+                'gst-0.10', 'pygtk.pth', 'pygtk.py', 'pygtk.pyc']
+
+    python_version = sys.version[:3]
+    global_path = os.path.join('/usr/lib', 'python' + python_version)
+    global_sitepackages = [os.path.join(global_path,
+                                        'dist-packages'),  # for Debian-based
+                           os.path.join(global_path,
+                                        'site-packages')]  # for others
+
+    for package in packages:
+        for pack_dir in global_sitepackages:
+            src = os.path.join(pack_dir, package)
+            dest = os.path.join(dest_dir, package)
+            if not os.path.exists(dest) and os.path.exists(src):
+                os.symlink(src, dest)
+
+
+def check_gstreamer():
+    try:
+        import gobject, pygst
+    except ImportError:
+        print 'Add Gstreamer'
+        add_gstreamer_packages()
+
diff --git a/timeside/core/tools/parameters.py b/timeside/core/tools/parameters.py
new file mode 100644 (file)
index 0000000..3101abb
--- /dev/null
@@ -0,0 +1,132 @@
+# -*- coding: utf-8 -*-
+
+#
+# Copyright (c) 2007-2014 Parisson SARL
+
+# This file is part of TimeSide.
+
+# TimeSide is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+
+# TimeSide is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with TimeSide.  If not, see <http://www.gnu.org/licenses/>.
+
+# Authors:
+#   Thomas Fillon <thomas  at parisson.com>
+
+
+from traits.api import HasTraits, Unicode, Int, Float, Range, Enum
+from traits.api import ListUnicode, List, Tuple
+from traits.api import TraitError
+
+import simplejson as json
+
+
+TRAIT_TYPES = {Unicode: 'str',
+               Int: 'int',
+               Float: 'float',
+               Range: 'range',
+               Enum: 'enum',
+               ListUnicode: 'list of str',
+               List: 'list'}
+
+
+class HasParam(object):
+    """
+    >>> class ParamClass(HasParam):
+    ...    class _Param(HasTraits):
+    ...        param1 = Unicode(desc='first or personal name',
+    ...                      label='First Name')
+    ...        param2 = Int()
+    ...        param3 = Float()
+    ...        param4 = Range(low=0, high=10, value=3)
+    >>>
+    >>> p = ParamClass()
+    >>> param_json = p.get_parameters()
+    >>> print param_json
+    {"param4": 3, "param3": 0.0, "param2": 0, "param1": ""}
+    >>> new_param_json = '{"param1": "plop", "param2": 7, "param3": 0.5, \
+    "param4": 8}'
+    >>> p.set_parameters(new_param_json)
+    >>> print p.get_parameters()
+    {"param4": 8, "param3": 0.5, "param2": 7, "param1": "plop"}
+    >>> v = p.param_view()
+    >>> print v
+    {"param4": {"default": 3, "type": "range"}, \
+"param3": {"default": 0.0, "type": "float"}, \
+"param2": {"default": 0, "type": "int"}, \
+"param1": {"default": "", "type": "str"}}
+    """
+    class _Param(HasTraits):
+        pass
+
+    def __init__(self):
+        super(HasParam, self).__init__()
+        self._parameters = self._Param()
+
+    def __setattr__(self, name, value):
+        if name is '_parameters':
+            super(HasParam, self).__setattr__(name, value)
+        elif name in self._parameters.trait_names():
+            self._parameters.__setattr__(name, value)
+            # Copy attributes as a regular attribute at class level
+            _value = self._parameters.__getattribute__(name)
+            super(HasParam, self).__setattr__(name, _value)
+        else:
+            super(HasParam, self).__setattr__(name, value)
+
+    def get_parameters(self):
+        list_traits = self._parameters.editable_traits()
+        param_dict = self._parameters.get(list_traits)
+        return json.dumps(param_dict)
+
+    def set_parameters(self, parameters):
+        if isinstance(parameters, basestring):
+            self.set_parameters(json.loads(parameters))
+        else:
+            for name, value in parameters.items():
+                self.__setattr__(name, value)
+
+    def validate_parameters(self, parameters):
+        """Validate parameters format against Traits specification
+        Input can be either a dictionary or a JSON string
+        Returns the validated parameters or raises a ValueError"""
+
+        if isinstance(parameters, basestring):
+            return self.validate_parameters(json.loads(parameters))
+        # Check key against traits name
+        traits_name = self._parameters.editable_traits()
+        for name in parameters:
+            if name not in traits_name:
+                raise KeyError(name)
+
+        try:
+            valid_params = {name: self._parameters.validate_trait(name, value)
+                            for name, value in parameters.items()}
+        except TraitError as e:
+            raise ValueError(str(e))
+
+        return valid_params
+
+    def param_view(self):
+        list_traits = self._parameters.editable_traits()
+        view = {}
+        for key in list_traits:
+            trait_type = self._parameters.trait(key).trait_type.__class__
+            default = self._parameters.trait(key).default
+            d = {'type': TRAIT_TYPES[trait_type],
+                 'default': default}
+            view[key] = d
+        return json.dumps(view)
+
+
+if __name__ == "__main__":
+    import doctest
+    doctest.testmod()
diff --git a/timeside/core/tools/test_samples.py b/timeside/core/tools/test_samples.py
new file mode 100644 (file)
index 0000000..ca202b1
--- /dev/null
@@ -0,0 +1,452 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+Created on Tue Oct  7 09:19:37 2014
+
+@author: thomas
+"""
+
+from __future__ import division
+
+import pygst
+pygst.require("0.10")
+import gobject
+import gst
+import numpy
+import scipy.signal.waveforms
+import os.path
+
+#import timeside
+
+
+class NumpySrc:
+    def __init__(self, array, samplerate):
+        self.appsrc = gst.element_factory_make("appsrc")
+        self.pos = 0
+        self.samplerate = samplerate
+        if array.ndim == 1:
+            array.resize((array.shape[0], 1))
+        self.length, self.channels = array.shape
+        self.array = array.astype("float32")
+        self.per_sample = gst.SECOND // samplerate
+        self.fac = self.channels * array.dtype.itemsize
+        #self.appsrc.set_property("size", (self.length * self.channels *
+        #                                  array.dtype.itemsize))
+        self.appsrc.set_property("format", gst.FORMAT_TIME)
+        capstr = """audio/x-raw-float,
+                    width=%d,
+                    depth=%d,
+                    rate=%d,
+                    channels=%d,
+                    endianness=(int)1234,
+                    signed=true""" % (self.array.dtype.itemsize*8,
+                                      self.array.dtype.itemsize*8,
+                                      self.samplerate,
+                                      self.channels)
+        self.appsrc.set_property("caps", gst.caps_from_string(capstr))
+        self.appsrc.set_property("stream-type", 0)  # Seekable
+        self.appsrc.set_property('block', True)
+
+        self.appsrc.connect("need-data", self.need_data)
+        self.appsrc.connect("seek-data", self.seek_data)
+        self.appsrc.connect("enough-data", self.enough_data)
+
+    def need_data(self, element, length):
+        #length = length // 64
+        if self.pos >= self.array.shape[0]:
+            element.emit("end-of-stream")
+        else:
+            avalaible_sample = self.length - self.pos
+            if avalaible_sample < length:
+                length = avalaible_sample
+            array = self.array[self.pos:self.pos+length]
+            buf = gst.Buffer(numpy.getbuffer(array.flatten()))
+
+            buf.timestamp = self.pos * self.per_sample
+            buf.duration = int(length*self.per_sample)
+            element.emit("push-buffer", buf)
+            self.pos += length
+
+    def seek_data(self, element, npos):
+        print 'seek %d' % npos
+        self.pos = npos // self.per_sample
+        return True
+
+    def enough_data(self, element):
+        print "----------- enough data ---------------"
+
+
+class SampleArray(object):
+    """Base Class for generating a data sample array"""
+
+    def __init__(self, duration=10, samplerate=44100):
+        self.samplerate = int(samplerate)
+        self.num_samples = int(numpy.ceil(duration * self.samplerate))
+        self.array = NotImplemented
+
+    @property
+    def time_samples(self):
+        return numpy.arange(0, self.num_samples)
+
+    @property
+    def duration(self):
+        return self.num_samples / self.samplerate
+
+    def __add__(self, other):
+        if not self.samplerate == other.samplerate:
+            raise ValueError("Samplerates mismatch")
+
+        sum_ = SampleArray(samplerate=self.samplerate)
+        sum_.num_samples = self.num_samples + other.num_samples
+        sum_.array = numpy.vstack([self.array, other.array])
+        return sum_
+
+    def __and__(self, other):
+        if not self.samplerate == other.samplerate:
+            raise ValueError("Samplerates mismatch")
+        if not self.num_samples == other.num_samples:
+            raise ValueError("Number of samples mismatch")
+
+        and_ = SampleArray(samplerate=self.samplerate)
+        and_.num_samples = self.num_samples
+        and_.array = numpy.hstack([self.array, other.array])
+        return and_
+
+
+class SineArray(SampleArray):
+    """Class for generating a Sine array"""
+    def __init__(self, frequency=440, duration=10, samplerate=44100,
+                 channels=1):
+        super(SineArray, self).__init__(duration=duration,
+                                        samplerate=samplerate)
+        self.frequency = frequency
+        self.array = numpy.sin((2 * numpy.pi * self.frequency *
+                               self.time_samples / self.samplerate))
+        self.array.resize(self.num_samples, 1)
+
+
+class SweepArray(SampleArray):
+    """Class for generating a Sweep array"""
+    def __init__(self, f0=20, f1=None, duration=10, samplerate=44100,
+                 method='logarithmic'):
+        super(SweepArray, self).__init__(duration=duration,
+                                         samplerate=samplerate)
+
+        self.f0 = f0 / samplerate
+        if f1 is None:
+            self.f1 = 0.5
+        else:
+            self.f1 = f1 / samplerate
+        self.method = method
+        self.array = scipy.signal.waveforms.chirp(t=self.time_samples,
+                                                  f0=self.f0,
+                                                  t1=self.time_samples[-1],
+                                                  f1=self.f1,
+                                                  method=self.method)
+        self.array.resize(self.num_samples, 1)
+
+
+class WhiteNoiseArray(SampleArray):
+    """Class for generating a white noise array"""
+    def __init__(self, duration=10, samplerate=44100):
+        super(WhiteNoiseArray, self).__init__(duration=duration,
+                                              samplerate=samplerate)
+        array = numpy.random.randn(self.num_samples, 1)
+        self.array = array / abs(array).max()
+
+
+class SilenceArray(SampleArray):
+    """Class for generating a silence"""
+    def __init__(self, duration=10, samplerate=44100):
+        super(SilenceArray, self).__init__(duration=duration,
+                                           samplerate=samplerate)
+
+        self.array = numpy.zeros((self.num_samples, 1))
+
+
+class gst_BuildSample(object):
+    def __init__(self, sample_array, output_file, gst_audio_encoder):
+        if not isinstance(sample_array, SampleArray):
+            raise ValueError("array must be a SampleArray subclass")
+        self.sample_array = sample_array
+        self.samplerate = self.sample_array.samplerate
+        self.output_file = output_file
+        if not isinstance(gst_audio_encoder, list):
+            gst_audio_encoder = [gst_audio_encoder]
+        self.gst_audio_encoder = gst_audio_encoder
+
+    def run(self):
+        pipeline = gst.Pipeline("pipeline")
+        gobject.threads_init()
+        mainloop = gobject.MainLoop()
+
+        numpy_src = NumpySrc(array=self.sample_array.array,
+                             samplerate=self.samplerate)
+
+        converter = gst.element_factory_make('audioconvert', 'converter')
+
+        encoder_muxer = []
+        for enc in self.gst_audio_encoder:
+            encoder_muxer.append(gst.element_factory_make(enc))
+
+        filesink = gst.element_factory_make('filesink', 'sink')
+        filesink.set_property('location', self.output_file)
+
+        pipe_elements = [numpy_src.appsrc, converter]
+        pipe_elements.extend(encoder_muxer)
+        pipe_elements.append(filesink)
+
+        pipeline.add(*pipe_elements)
+        gst.element_link_many(*pipe_elements)
+
+        def _on_new_pad(self, source, pad, target_pad):
+            print 'on_new_pad'
+            if not pad.is_linked():
+                if target_pad.is_linked():
+                    target_pad.get_peer().unlink(target_pad)
+                pad.link(target_pad)
+
+        def on_eos(bus, msg):
+            pipeline.set_state(gst.STATE_NULL)
+            mainloop.quit()
+
+        def on_error(bus, msg):
+            err, debug_info = msg.parse_error()
+            print ("Error received from element %s: %s" % (msg.src.get_name(),
+                                                           err))
+            print ("Debugging information: %s" % debug_info)
+            mainloop.quit()
+
+        pipeline.set_state(gst.STATE_PLAYING)
+        bus = pipeline.get_bus()
+        bus.add_signal_watch()
+        bus.connect('message::eos', on_eos)
+        bus.connect("message::error", on_error)
+
+        mainloop.run()
+
+
+def generate_sample_file(filename, samples_dir, gst_audio_encoder,
+                         sample_array, overwrite=False):
+    sample_file = os.path.join(samples_dir, filename)
+
+    if overwrite or not os.path.exists(sample_file):
+            gst_builder = gst_BuildSample(sample_array=sample_array,
+                                          output_file=sample_file,
+                                          gst_audio_encoder=gst_audio_encoder)
+            gst_builder.run()
+    return sample_file
+
+
+def generateSamples(overwrite=False):
+    from timeside import __file__ as ts_file
+    ts_path = os.path.split(os.path.abspath(ts_file))[0]
+    tests_dir = os.path.abspath(os.path.join(ts_path, '../tests'))
+    if os.path.isdir(tests_dir):
+        samples_dir = os.path.abspath(os.path.join(tests_dir, 'samples'))
+        if not os.path.isdir(samples_dir):
+            os.makedirs(samples_dir)
+    else:
+        import tempfile
+        samples_dir = tempfile.mkdtemp(suffix="ts_samples")
+
+    samples = dict()
+
+    # --------- Sweeps ---------
+    # sweep 44100 mono wav
+    filename = 'sweep_mono.wav'
+    samplerate = 44100
+    gst_audio_encoder = 'wavenc'
+    sweep_mono = SweepArray(duration=8, samplerate=samplerate)
+    sample_file = generate_sample_file(filename, samples_dir,
+                                       gst_audio_encoder,
+                                       sample_array=sweep_mono,
+                                       overwrite=overwrite)
+    samples.update({filename: sample_file})
+
+    # sweep 44100 stereo wav
+    sweep_stereo = sweep_mono & sweep_mono
+    filename = 'sweep.wav'
+    gst_audio_encoder = 'wavenc'
+    sweep_mono = SweepArray(duration=8, samplerate=samplerate)
+    sample_file = generate_sample_file(filename, samples_dir,
+                                       gst_audio_encoder,
+                                       sample_array=sweep_stereo,
+                                       overwrite=overwrite)
+    samples.update({filename: sample_file})
+
+   # sweep 44100 stereo mp3
+    filename = 'sweep.mp3'
+    gst_audio_encoder = ['lamemp3enc', 'xingmux', 'id3v2mux']
+    sweep_mono = SweepArray(duration=8, samplerate=samplerate)
+    sample_file = generate_sample_file(filename, samples_dir,
+                                       gst_audio_encoder,
+                                       sample_array=sweep_stereo,
+                                       overwrite=overwrite)
+    samples.update({filename: sample_file})
+
+   # sweep 44100 stereo flac
+    filename = 'sweep.flac'
+    gst_audio_encoder = 'flacenc'
+    sweep_mono = SweepArray(duration=8, samplerate=samplerate)
+    sample_file = generate_sample_file(filename, samples_dir,
+                                       gst_audio_encoder,
+                                       sample_array=sweep_stereo,
+                                       overwrite=overwrite)
+    samples.update({filename: sample_file})
+
+   # sweep 44100 stereo ogg
+    filename = 'sweep.ogg'
+    gst_audio_encoder = ['vorbisenc', 'oggmux']
+    sweep_mono = SweepArray(duration=8, samplerate=samplerate)
+    sample_file = generate_sample_file(filename, samples_dir,
+                                       gst_audio_encoder,
+                                       sample_array=sweep_stereo,
+                                       overwrite=overwrite)
+    samples.update({filename: sample_file})
+
+    # sweep 32000 stereo wav
+    samplerate = 32000
+    sweep_mono = SweepArray(duration=8, samplerate=samplerate)
+    sweep_stereo = sweep_mono & sweep_mono
+
+    filename = 'sweep_32000.wav'
+    gst_audio_encoder = 'wavenc'
+    sweep_mono = SweepArray(duration=8, samplerate=samplerate)
+    sample_file = generate_sample_file(filename, samples_dir,
+                                       gst_audio_encoder,
+                                       sample_array=sweep_stereo,
+                                       overwrite=overwrite)
+    samples.update({filename: sample_file})
+
+    # --------- Sines ---------
+    # sine at 440Hz,  44100 mono wav
+    filename = 'sine440Hz_mono.wav'
+    samplerate = 44100
+    gst_audio_encoder = 'wavenc'
+    sweep_mono = SineArray(duration=8, samplerate=samplerate, frequency=440)
+    sample_file = generate_sample_file(filename, samples_dir,
+                                       gst_audio_encoder,
+                                       sample_array=sweep_mono,
+                                       overwrite=overwrite)
+    samples.update({filename: sample_file})
+
+    # Short 1s sine at 440Hz,  44100 mono wav
+    filename = 'sine440Hz_mono_1s.wav'
+    samplerate = 44100
+    gst_audio_encoder = 'wavenc'
+    sweep_mono = SineArray(duration=1, samplerate=samplerate, frequency=440)
+    sample_file = generate_sample_file(filename, samples_dir,
+                                       gst_audio_encoder,
+                                       sample_array=sweep_mono,
+                                       overwrite=overwrite)
+    samples.update({filename: sample_file})
+
+    # sine at 440Hz,  44100 stereo wav
+    filename = 'sine440Hz.wav'
+    sweep_stereo = sweep_mono & sweep_mono
+    gst_audio_encoder = 'wavenc'
+    sweep_mono = SineArray(duration=8, samplerate=samplerate, frequency=440)
+    sample_file = generate_sample_file(filename, samples_dir,
+                                       gst_audio_encoder,
+                                       sample_array=sweep_stereo,
+                                       overwrite=overwrite)
+    samples.update({filename: sample_file})
+
+    # sine at 440Hz,  44100 stereo mp3
+    filename = 'sine440Hz.mp3'
+    gst_audio_encoder = ['lamemp3enc', 'xingmux', 'id3v2mux']
+    sweep_mono = SineArray(duration=8, samplerate=samplerate, frequency=440)
+    sample_file = generate_sample_file(filename, samples_dir,
+                                       gst_audio_encoder,
+                                       sample_array=sweep_stereo,
+                                       overwrite=overwrite)
+    samples.update({filename: sample_file})
+
+    # sine at 440Hz,  44100 stereo ogg
+    filename = 'sine440Hz.ogg'
+    gst_audio_encoder = ['vorbisenc', 'oggmux']
+    sweep_mono = SineArray(duration=8, samplerate=samplerate, frequency=440)
+    sample_file = generate_sample_file(filename, samples_dir,
+                                       gst_audio_encoder,
+                                       sample_array=sweep_stereo,
+                                       overwrite=overwrite)
+    samples.update({filename: sample_file})
+
+    # --------- Equal tempered scale ---------
+    filename = 'C4_scale.wav'
+    samplerate = 44100
+    f_C4 = 261.63
+    f_D4 = 293.66
+    f_E4 = 329.63
+    f_F4 = 349.23
+    f_G4 = 392.00
+    f_A4 = 440.00
+    f_B4 = 493.88
+    f_C5 = 523.25
+    sineC4 = SineArray(duration=1, samplerate=samplerate, frequency=f_C4)
+    sineD4 = SineArray(duration=1, samplerate=samplerate, frequency=f_D4)
+    sineE4 = SineArray(duration=1, samplerate=samplerate, frequency=f_E4)
+    sineF4 = SineArray(duration=1, samplerate=samplerate, frequency=f_F4)
+    sineG4 = SineArray(duration=1, samplerate=samplerate, frequency=f_G4)
+    sineA4 = SineArray(duration=1, samplerate=samplerate, frequency=f_A4)
+    sineB4 = SineArray(duration=1, samplerate=samplerate, frequency=f_B4)
+    sineC5 = SineArray(duration=1, samplerate=samplerate, frequency=f_C5)
+
+    silence = SilenceArray(duration=0.2, samplerate=samplerate)
+
+    scale = (sineC4 + silence + sineD4 + silence + sineE4 + silence +
+             sineF4 + silence + sineG4 + silence + sineA4 + silence +
+             sineB4 + silence + sineC5)
+
+    gst_audio_encoder = 'wavenc'
+    sample_file = generate_sample_file(filename, samples_dir,
+                                       gst_audio_encoder,
+                                       sample_array=scale,
+                                       overwrite=overwrite)
+    samples.update({filename: sample_file})
+
+    # --------- White noise ---------
+    # white noise - 44100Hz mono
+    filename = 'white_noise_mono.wav'
+    samplerate = 44100
+    noise = WhiteNoiseArray(duration=8, samplerate=samplerate)
+    gst_audio_encoder = 'wavenc'
+    sample_file = generate_sample_file(filename, samples_dir,
+                                       gst_audio_encoder,
+                                       sample_array=noise,
+                                       overwrite=overwrite)
+    samples.update({filename: sample_file})
+
+    # white noise - 44100Hz stereo
+    filename = 'white_noise.wav'
+    samplerate = 44100
+    noise = WhiteNoiseArray(duration=8, samplerate=samplerate)
+    noise_stereo = noise & noise
+    gst_audio_encoder = 'wavenc'
+    sample_file = generate_sample_file(filename, samples_dir,
+                                       gst_audio_encoder,
+                                       sample_array=noise_stereo,
+                                       overwrite=overwrite)
+    samples.update({filename: sample_file})
+
+    # white noise - 32000Hz stereo
+    filename = 'white_noise_32000.wav'
+    samplerate = 32000
+    noise = WhiteNoiseArray(duration=8, samplerate=samplerate)
+    noise_stereo = noise & noise
+    gst_audio_encoder = 'wavenc'
+    sample_file = generate_sample_file(filename, samples_dir,
+                                       gst_audio_encoder,
+                                       sample_array=noise_stereo,
+                                       overwrite=overwrite)
+    samples.update({filename: sample_file})
+
+    return samples
+
+
+samples = generateSamples()
+
+
+if __name__ == '__main__':
+    generateSamples()
diff --git a/timeside/tools/__init__.py b/timeside/tools/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/timeside/tools/buffering.py b/timeside/tools/buffering.py
deleted file mode 100644 (file)
index bcc4e0e..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Copyright (c) 2014 Parisson SARL
-# Copyright (c) 2014 Thomas Fillon <thomas@parisson.com>
-
-# This file is part of TimeSide.
-
-# TimeSide is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 2 of the License, or
-# (at your option) any later version.
-
-# TimeSide is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with TimeSide.  If not, see <http://www.gnu.org/licenses/>.
-#
-# Author : Thomas Fillon <thomas@parisson.com>
-
-import tables
-from tempfile import NamedTemporaryFile
-import numpy as np
-
-class BufferTable(object):
-    def __init__(self, array_names=None):
-        self._tempfile = NamedTemporaryFile(mode='w', suffix='.h5',
-                                            prefix='ts_buf_',
-                                            delete=True)
-        self.fileh = tables.openFile(self._tempfile.name, mode='w')
-
-        if not array_names:
-            array_names = []
-        if isinstance(array_names, list):
-            self.array_names = array_names
-        else:
-            self.array_names = [array_names]
-        for name in array_names:
-            if not isinstance(name, basestring):
-                raise(TypeError, 'String argument require in array_names')
-
-    def __getitem__(self, name):
-        return self.fileh.root.__getattr__(name)
-
-    #def __set_item__(self, name, value):
-    #    self.fileh.root.__setattr__(name, value)
-
-    def append(self, name, new_array):
-        try:
-            if new_array.shape:
-                self.fileh.root.__getattr__(name).append(new_array[np.newaxis,
-                                                                   :])
-            else:
-                self.fileh.root.__getattr__(name).append([new_array])
-        except tables.exceptions.NoSuchNodeError:
-            if name not in self.array_names:
-                self.array_names.append(name)
-             # The following is compatible with pytables 3 only
-             #self.fileh.create_earray(where=self.fileh.root,
-             #                         name=name,
-             #                         obj=[new_array])
-            atom = tables.Atom.from_dtype(new_array.dtype)
-            dim_list = [0]
-            dim_list.extend([dim for dim in new_array.shape])
-            shape = tuple(dim_list)
-
-            self.fileh.createEArray(where=self.fileh.root,
-                                    name=name,
-                                    atom=atom,
-                                    shape=shape)
-            self.append(name, new_array)
-
-    def close(self):
-        for name in self.array_names:
-            self.fileh.removeNode(self.fileh.root, name)
-        self.fileh.close()
-        self._tempfile.close()
diff --git a/timeside/tools/cache.py b/timeside/tools/cache.py
deleted file mode 100644 (file)
index 592524a..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2006-2010 Guillaume Pellerin
-
-# <yomguy@parisson.com>
-
-# This software is a computer program whose purpose is to stream audio
-# and video data through icecast2 servers.
-
-# This software is governed by the CeCILL license under French law and
-# abiding by the rules of distribution of free software. You can use,
-# modify and/ or redistribute the software under the terms of the CeCILL
-# license as circulated by CEA, CNRS and INRIA at the following URL
-# "http://www.cecill.info".
-
-# As a counterpart to the access to the source code and  rights to copy,
-# modify and redistribute granted by the license, users are provided only
-# with a limited warranty and the software's author, the holder of the
-# economic rights, and the successive licensors have only limited
-# liability.
-
-# In this respect, the user's attention is drawn to the risks associated
-# with loading, using,  modifying and/or developing or reproducing the
-# software by the user in light of its specific status of free software,
-# that may mean that it is complicated to manipulate, and that also
-# therefore means that it is reserved for developers and  experienced
-# professionals having in-depth computer knowledge. Users are therefore
-# encouraged to load and test the software's suitability as regards their
-# requirements in conditions enabling the security of their systems and/or
-# data to be ensured and, more generally, to use and operate it in the
-# same conditions as regards security.
-
-# The fact that you are presently reading this means that you have had
-# knowledge of the CeCILL license and that you accept its terms.
-
-# Author: Guillaume Pellerin <yomguy@parisson.com>
-
-import os
-import xml.dom.minidom
-
-
-class Cache(object):
-
-    def __init__(self, dir, params=None):
-        self.dir = dir
-        self.params = params
-        self.files = self.get_files()
-
-    def get_files(self):
-        list = []
-        for root, dirs, files in os.walk(self.dir):
-            for file in files:
-                list.append(file)
-        return list
-
-    def exists(self, file):
-        self.files = self.get_files()
-        return file in self.files
-
-    def write_bin(self, data, file):
-        path = self.dir + os.sep + file
-        f = open(path, 'w')
-        f.write(data)
-        f.close()
-
-    def read_bin(self, file):
-        path = self.dir + os.sep + file
-        f = open(path, 'r')
-        data = f.read()
-        f.close()
-        return data
-
-    def read_stream_bin(self, file):
-        path = self.dir + os.sep + file
-        chunk_size = 0x1000
-        f = open(path, 'r')
-        while True:
-            _chunk = f.read(chunk_size)
-            if not len(_chunk):
-                break
-            yield _chunk
-        f.close()
-
-    def write_stream_bin(self, chunk, file_object):
-        file_object.write(chunk)
-
-    def read_analyzer_xml(self, file):
-        list = []
-        path = self.dir + os.sep + file
-        doc = xml.dom.minidom.parse(path)
-        for data in doc.documentElement.getElementsByTagName('data'):
-            name = data.getAttribute('name')
-            id = data.getAttribute('id')
-            unit = data.getAttribute('unit')
-            value = data.getAttribute('value')
-            list.append({'name': name, 'id': id, 'unit': unit, 'value': value})
-        return list
-
-    def write_analyzer_xml(self, data_list, file):
-        path = self.dir + os.sep + file
-        doc = xml.dom.minidom.Document()
-        root = doc.createElement('telemeta')
-        doc.appendChild(root)
-        for data in data_list:
-            name = data['name']
-            id = data['id']
-            unit = data['unit']
-            value = data['value']
-            node = doc.createElement('data')
-            node.setAttribute('name', name)
-            node.setAttribute('id', id)
-            node.setAttribute('unit', unit)
-            node.setAttribute('value', str(value))
-            root.appendChild(node)
-        f = open(path, "w")
-        f.write(xml.dom.minidom.Document.toprettyxml(doc))
-        f.close()
diff --git a/timeside/tools/gstutils.py b/timeside/tools/gstutils.py
deleted file mode 100644 (file)
index 6d06a3e..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-from numpy import getbuffer, frombuffer
-
-import pygst
-pygst.require('0.10')
-import gst
-import gobject
-gobject.threads_init()
-
-import threading
-
-
-def numpy_array_to_gst_buffer(frames, chunk_size, num_samples, sample_rate):
-    from gst import Buffer
-    """ gstreamer buffer to numpy array conversion """
-    buf = Buffer(getbuffer(frames.astype("float32")))
-    # Set its timestamp and duration
-    buf.timestamp = gst.util_uint64_scale(num_samples, gst.SECOND, sample_rate)
-    buf.duration = gst.util_uint64_scale(chunk_size, gst.SECOND, sample_rate)
-    return buf
-
-
-def gst_buffer_to_numpy_array(buf, chan):
-    """ gstreamer buffer to numpy array conversion """
-    samples = frombuffer(buf.data, dtype='float32').reshape((-1, chan))
-    return samples
-
-
-class MainloopThread(threading.Thread):
-
-    def __init__(self, mainloop):
-        threading.Thread.__init__(self)
-        self.mainloop = mainloop
-
-    def run(self):
-        self.mainloop.run()
diff --git a/timeside/tools/hdf5.py b/timeside/tools/hdf5.py
deleted file mode 100644 (file)
index 2db446e..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (c) 2007-2013 Parisson SARL
-
-# This file is part of TimeSide.
-
-# TimeSide is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 2 of the License, or
-# (at your option) any later version.
-
-# TimeSide is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with TimeSide.  If not, see <http://www.gnu.org/licenses/>.
-
-# Author:
-#   Thomas Fillon <thomas  at parisson.com>
-
-
-def dict_to_hdf5(dict_like, h5group):
-    """
-    Save a dictionnary-like object inside a h5 file group
-    """
-    # Write attributes
-    attrs = dict_like.keys()
-    for name in attrs:
-        if dict_like[name] is not None:
-            h5group.attrs[str(name)] = dict_like[name]
-
-
-def dict_from_hdf5(dict_like, h5group):
-    """
-    Load a dictionnary-like object from a h5 file group
-    """
-    # Read attributes
-    for name, value in h5group.attrs.items():
-        dict_like[name] = value
diff --git a/timeside/tools/logger.py b/timeside/tools/logger.py
deleted file mode 100644 (file)
index 1405627..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-import logging
-
-
-class Logger:
-
-    """A logging object"""
-
-    def __init__(self, file):
-        self.logger = logging.getLogger('myapp')
-        self.hdlr = logging.FileHandler(file)
-        self.formatter = logging.Formatter(
-            '%(asctime)s %(levelname)s %(message)s')
-        self.hdlr.setFormatter(self.formatter)
-        self.logger.addHandler(self.hdlr)
-        self.logger.setLevel(logging.INFO)
-
-    def write_info(self, message):
-        self.logger.info(message)
-
-    def write_error(self, message):
-        self.logger.error(message)
diff --git a/timeside/tools/package.py b/timeside/tools/package.py
deleted file mode 100644 (file)
index a31b887..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (c) 2013-2014 Thomas Fillon <thomas.fillon@parisson.com>
-
-# This file is part of TimeSide.
-
-# TimeSide is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 2 of the License, or
-# (at your option) any later version.
-
-# TimeSide is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with TimeSide.  If not, see <http://www.gnu.org/licenses/>.
-
-# Author: Thomas Fillon <thomas.fillon@parisson.com>
-
-
-from importlib import import_module
-import warnings
-
-from ..core.exceptions import VampImportError
-
-def discover_modules(subpackage, package=None):
-    import pkgutil
-
-    if package:
-        try:
-            _pkg = import_module('.' + subpackage, package)
-        except ImportError as e:
-            raise e
-    else:
-        _pkg = import_module(subpackage)
-
-    pkg_path = _pkg.__path__
-    pkg_prefix = _pkg.__name__ + '.'
-
-    _list = [import_module_with_exceptions(modname)
-             for importer, modname, ispkg
-             in pkgutil.walk_packages(pkg_path, pkg_prefix)]
-
-    modules_list = [mod for mod in _list if mod is not None]
-    return modules_list
-
-
-def import_module_with_exceptions(name, package=None):
-    """Wrapper around importlib.import_module to import TimeSide subpackage
-    and ignoring ImportError if Aubio, Yaafe and Vamp Host are not available"""
-
-    from timeside.core import _WITH_AUBIO, _WITH_YAAFE, _WITH_VAMP
-
-    if name.count('.server.'):
-        # TODO:
-        # Temporary skip all timeside.server submodules before check dependencies
-        return
-    try:
-        import_module(name, package)
-    except VampImportError:
-        # No Vamp Host
-        if _WITH_VAMP:
-            raise VampImportError
-        else:
-            # Ignore Vamp ImportError
-            return
-    except ImportError as e:
-        if str(e).count('yaafelib') and not _WITH_YAAFE:
-            # Ignore Yaafe ImportError
-            return
-        elif str(e).count('aubio') and not _WITH_AUBIO:
-            # Ignore Aubio ImportError
-            return
-        elif str(e).count('DJANGO_SETTINGS_MODULE'):
-            # Ignore module requiring DJANGO_SETTINGS_MODULE in environnement
-            return
-        else:
-            print (name, package)
-            raise e
-    return name
-
-
-# Check Availability of external Audio feature extraction librairies
-def check_aubio():
-    "Check Aubio availability"
-    try:
-        import aubio
-    except ImportError:
-        warnings.warn('Aubio librairy is not available', ImportWarning,
-                      stacklevel=2)
-        _WITH_AUBIO = False
-    else:
-        _WITH_AUBIO = True
-        del aubio
-
-    return _WITH_AUBIO
-
-
-def check_yaafe():
-    "Check Aubio availability"
-    try:
-        import yaafelib
-    except ImportError:
-        warnings.warn('Yaafe librairy is not available', ImportWarning,
-                      stacklevel=2)
-        _WITH_YAAFE = False
-    else:
-        _WITH_YAAFE = True
-        del yaafelib
-    return _WITH_YAAFE
-
-
-def check_vamp():
-    "Check Vamp host availability"
-    from ..core.exceptions import VampImportError
-
-    try:
-        from timeside.plugins.analyzer.externals import vamp_plugin
-    except VampImportError:
-        warnings.warn('Vamp host is not available', ImportWarning,
-                      stacklevel=2)
-        _WITH_VAMP = False
-    else:
-        _WITH_VAMP = True
-        del vamp_plugin
-
-    return _WITH_VAMP
-
-def add_gstreamer_packages():
-    import os
-    import sys
-    from distutils.sysconfig import get_python_lib
-
-    dest_dir = get_python_lib()
-
-    packages = ['gobject', 'glib', 'pygst', 'pygst.pyc', 'pygst.pth',
-                'gst-0.10', 'pygtk.pth', 'pygtk.py', 'pygtk.pyc']
-
-    python_version = sys.version[:3]
-    global_path = os.path.join('/usr/lib', 'python' + python_version)
-    global_sitepackages = [os.path.join(global_path,
-                                        'dist-packages'),  # for Debian-based
-                           os.path.join(global_path,
-                                        'site-packages')]  # for others
-
-    for package in packages:
-        for pack_dir in global_sitepackages:
-            src = os.path.join(pack_dir, package)
-            dest = os.path.join(dest_dir, package)
-            if not os.path.exists(dest) and os.path.exists(src):
-                os.symlink(src, dest)
-
-
-def check_gstreamer():
-    try:
-        import gobject, pygst
-    except ImportError:
-        print 'Add Gstreamer'
-        add_gstreamer_packages()
-
diff --git a/timeside/tools/parameters.py b/timeside/tools/parameters.py
deleted file mode 100644 (file)
index 3101abb..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-# -*- coding: utf-8 -*-
-
-#
-# Copyright (c) 2007-2014 Parisson SARL
-
-# This file is part of TimeSide.
-
-# TimeSide is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 2 of the License, or
-# (at your option) any later version.
-
-# TimeSide is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with TimeSide.  If not, see <http://www.gnu.org/licenses/>.
-
-# Authors:
-#   Thomas Fillon <thomas  at parisson.com>
-
-
-from traits.api import HasTraits, Unicode, Int, Float, Range, Enum
-from traits.api import ListUnicode, List, Tuple
-from traits.api import TraitError
-
-import simplejson as json
-
-
-TRAIT_TYPES = {Unicode: 'str',
-               Int: 'int',
-               Float: 'float',
-               Range: 'range',
-               Enum: 'enum',
-               ListUnicode: 'list of str',
-               List: 'list'}
-
-
-class HasParam(object):
-    """
-    >>> class ParamClass(HasParam):
-    ...    class _Param(HasTraits):
-    ...        param1 = Unicode(desc='first or personal name',
-    ...                      label='First Name')
-    ...        param2 = Int()
-    ...        param3 = Float()
-    ...        param4 = Range(low=0, high=10, value=3)
-    >>>
-    >>> p = ParamClass()
-    >>> param_json = p.get_parameters()
-    >>> print param_json
-    {"param4": 3, "param3": 0.0, "param2": 0, "param1": ""}
-    >>> new_param_json = '{"param1": "plop", "param2": 7, "param3": 0.5, \
-    "param4": 8}'
-    >>> p.set_parameters(new_param_json)
-    >>> print p.get_parameters()
-    {"param4": 8, "param3": 0.5, "param2": 7, "param1": "plop"}
-    >>> v = p.param_view()
-    >>> print v
-    {"param4": {"default": 3, "type": "range"}, \
-"param3": {"default": 0.0, "type": "float"}, \
-"param2": {"default": 0, "type": "int"}, \
-"param1": {"default": "", "type": "str"}}
-    """
-    class _Param(HasTraits):
-        pass
-
-    def __init__(self):
-        super(HasParam, self).__init__()
-        self._parameters = self._Param()
-
-    def __setattr__(self, name, value):
-        if name is '_parameters':
-            super(HasParam, self).__setattr__(name, value)
-        elif name in self._parameters.trait_names():
-            self._parameters.__setattr__(name, value)
-            # Copy attributes as a regular attribute at class level
-            _value = self._parameters.__getattribute__(name)
-            super(HasParam, self).__setattr__(name, _value)
-        else:
-            super(HasParam, self).__setattr__(name, value)
-
-    def get_parameters(self):
-        list_traits = self._parameters.editable_traits()
-        param_dict = self._parameters.get(list_traits)
-        return json.dumps(param_dict)
-
-    def set_parameters(self, parameters):
-        if isinstance(parameters, basestring):
-            self.set_parameters(json.loads(parameters))
-        else:
-            for name, value in parameters.items():
-                self.__setattr__(name, value)
-
-    def validate_parameters(self, parameters):
-        """Validate parameters format against Traits specification
-        Input can be either a dictionary or a JSON string
-        Returns the validated parameters or raises a ValueError"""
-
-        if isinstance(parameters, basestring):
-            return self.validate_parameters(json.loads(parameters))
-        # Check key against traits name
-        traits_name = self._parameters.editable_traits()
-        for name in parameters:
-            if name not in traits_name:
-                raise KeyError(name)
-
-        try:
-            valid_params = {name: self._parameters.validate_trait(name, value)
-                            for name, value in parameters.items()}
-        except TraitError as e:
-            raise ValueError(str(e))
-
-        return valid_params
-
-    def param_view(self):
-        list_traits = self._parameters.editable_traits()
-        view = {}
-        for key in list_traits:
-            trait_type = self._parameters.trait(key).trait_type.__class__
-            default = self._parameters.trait(key).default
-            d = {'type': TRAIT_TYPES[trait_type],
-                 'default': default}
-            view[key] = d
-        return json.dumps(view)
-
-
-if __name__ == "__main__":
-    import doctest
-    doctest.testmod()
diff --git a/timeside/tools/test_samples.py b/timeside/tools/test_samples.py
deleted file mode 100644 (file)
index ca202b1..0000000
+++ /dev/null
@@ -1,452 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-"""
-Created on Tue Oct  7 09:19:37 2014
-
-@author: thomas
-"""
-
-from __future__ import division
-
-import pygst
-pygst.require("0.10")
-import gobject
-import gst
-import numpy
-import scipy.signal.waveforms
-import os.path
-
-#import timeside
-
-
-class NumpySrc:
-    def __init__(self, array, samplerate):
-        self.appsrc = gst.element_factory_make("appsrc")
-        self.pos = 0
-        self.samplerate = samplerate
-        if array.ndim == 1:
-            array.resize((array.shape[0], 1))
-        self.length, self.channels = array.shape
-        self.array = array.astype("float32")
-        self.per_sample = gst.SECOND // samplerate
-        self.fac = self.channels * array.dtype.itemsize
-        #self.appsrc.set_property("size", (self.length * self.channels *
-        #                                  array.dtype.itemsize))
-        self.appsrc.set_property("format", gst.FORMAT_TIME)
-        capstr = """audio/x-raw-float,
-                    width=%d,
-                    depth=%d,
-                    rate=%d,
-                    channels=%d,
-                    endianness=(int)1234,
-                    signed=true""" % (self.array.dtype.itemsize*8,
-                                      self.array.dtype.itemsize*8,
-                                      self.samplerate,
-                                      self.channels)
-        self.appsrc.set_property("caps", gst.caps_from_string(capstr))
-        self.appsrc.set_property("stream-type", 0)  # Seekable
-        self.appsrc.set_property('block', True)
-
-        self.appsrc.connect("need-data", self.need_data)
-        self.appsrc.connect("seek-data", self.seek_data)
-        self.appsrc.connect("enough-data", self.enough_data)
-
-    def need_data(self, element, length):
-        #length = length // 64
-        if self.pos >= self.array.shape[0]:
-            element.emit("end-of-stream")
-        else:
-            avalaible_sample = self.length - self.pos
-            if avalaible_sample < length:
-                length = avalaible_sample
-            array = self.array[self.pos:self.pos+length]
-            buf = gst.Buffer(numpy.getbuffer(array.flatten()))
-
-            buf.timestamp = self.pos * self.per_sample
-            buf.duration = int(length*self.per_sample)
-            element.emit("push-buffer", buf)
-            self.pos += length
-
-    def seek_data(self, element, npos):
-        print 'seek %d' % npos
-        self.pos = npos // self.per_sample
-        return True
-
-    def enough_data(self, element):
-        print "----------- enough data ---------------"
-
-
-class SampleArray(object):
-    """Base Class for generating a data sample array"""
-
-    def __init__(self, duration=10, samplerate=44100):
-        self.samplerate = int(samplerate)
-        self.num_samples = int(numpy.ceil(duration * self.samplerate))
-        self.array = NotImplemented
-
-    @property
-    def time_samples(self):
-        return numpy.arange(0, self.num_samples)
-
-    @property
-    def duration(self):
-        return self.num_samples / self.samplerate
-
-    def __add__(self, other):
-        if not self.samplerate == other.samplerate:
-            raise ValueError("Samplerates mismatch")
-
-        sum_ = SampleArray(samplerate=self.samplerate)
-        sum_.num_samples = self.num_samples + other.num_samples
-        sum_.array = numpy.vstack([self.array, other.array])
-        return sum_
-
-    def __and__(self, other):
-        if not self.samplerate == other.samplerate:
-            raise ValueError("Samplerates mismatch")
-        if not self.num_samples == other.num_samples:
-            raise ValueError("Number of samples mismatch")
-
-        and_ = SampleArray(samplerate=self.samplerate)
-        and_.num_samples = self.num_samples
-        and_.array = numpy.hstack([self.array, other.array])
-        return and_
-
-
-class SineArray(SampleArray):
-    """Class for generating a Sine array"""
-    def __init__(self, frequency=440, duration=10, samplerate=44100,
-                 channels=1):
-        super(SineArray, self).__init__(duration=duration,
-                                        samplerate=samplerate)
-        self.frequency = frequency
-        self.array = numpy.sin((2 * numpy.pi * self.frequency *
-                               self.time_samples / self.samplerate))
-        self.array.resize(self.num_samples, 1)
-
-
-class SweepArray(SampleArray):
-    """Class for generating a Sweep array"""
-    def __init__(self, f0=20, f1=None, duration=10, samplerate=44100,
-                 method='logarithmic'):
-        super(SweepArray, self).__init__(duration=duration,
-                                         samplerate=samplerate)
-
-        self.f0 = f0 / samplerate
-        if f1 is None:
-            self.f1 = 0.5
-        else:
-            self.f1 = f1 / samplerate
-        self.method = method
-        self.array = scipy.signal.waveforms.chirp(t=self.time_samples,
-                                                  f0=self.f0,
-                                                  t1=self.time_samples[-1],
-                                                  f1=self.f1,
-                                                  method=self.method)
-        self.array.resize(self.num_samples, 1)
-
-
-class WhiteNoiseArray(SampleArray):
-    """Class for generating a white noise array"""
-    def __init__(self, duration=10, samplerate=44100):
-        super(WhiteNoiseArray, self).__init__(duration=duration,
-                                              samplerate=samplerate)
-        array = numpy.random.randn(self.num_samples, 1)
-        self.array = array / abs(array).max()
-
-
-class SilenceArray(SampleArray):
-    """Class for generating a silence"""
-    def __init__(self, duration=10, samplerate=44100):
-        super(SilenceArray, self).__init__(duration=duration,
-                                           samplerate=samplerate)
-
-        self.array = numpy.zeros((self.num_samples, 1))
-
-
-class gst_BuildSample(object):
-    def __init__(self, sample_array, output_file, gst_audio_encoder):
-        if not isinstance(sample_array, SampleArray):
-            raise ValueError("array must be a SampleArray subclass")
-        self.sample_array = sample_array
-        self.samplerate = self.sample_array.samplerate
-        self.output_file = output_file
-        if not isinstance(gst_audio_encoder, list):
-            gst_audio_encoder = [gst_audio_encoder]
-        self.gst_audio_encoder = gst_audio_encoder
-
-    def run(self):
-        pipeline = gst.Pipeline("pipeline")
-        gobject.threads_init()
-        mainloop = gobject.MainLoop()
-
-        numpy_src = NumpySrc(array=self.sample_array.array,
-                             samplerate=self.samplerate)
-
-        converter = gst.element_factory_make('audioconvert', 'converter')
-
-        encoder_muxer = []
-        for enc in self.gst_audio_encoder:
-            encoder_muxer.append(gst.element_factory_make(enc))
-
-        filesink = gst.element_factory_make('filesink', 'sink')
-        filesink.set_property('location', self.output_file)
-
-        pipe_elements = [numpy_src.appsrc, converter]
-        pipe_elements.extend(encoder_muxer)
-        pipe_elements.append(filesink)
-
-        pipeline.add(*pipe_elements)
-        gst.element_link_many(*pipe_elements)
-
-        def _on_new_pad(self, source, pad, target_pad):
-            print 'on_new_pad'
-            if not pad.is_linked():
-                if target_pad.is_linked():
-                    target_pad.get_peer().unlink(target_pad)
-                pad.link(target_pad)
-
-        def on_eos(bus, msg):
-            pipeline.set_state(gst.STATE_NULL)
-            mainloop.quit()
-
-        def on_error(bus, msg):
-            err, debug_info = msg.parse_error()
-            print ("Error received from element %s: %s" % (msg.src.get_name(),
-                                                           err))
-            print ("Debugging information: %s" % debug_info)
-            mainloop.quit()
-
-        pipeline.set_state(gst.STATE_PLAYING)
-        bus = pipeline.get_bus()
-        bus.add_signal_watch()
-        bus.connect('message::eos', on_eos)
-        bus.connect("message::error", on_error)
-
-        mainloop.run()
-
-
-def generate_sample_file(filename, samples_dir, gst_audio_encoder,
-                         sample_array, overwrite=False):
-    sample_file = os.path.join(samples_dir, filename)
-
-    if overwrite or not os.path.exists(sample_file):
-            gst_builder = gst_BuildSample(sample_array=sample_array,
-                                          output_file=sample_file,
-                                          gst_audio_encoder=gst_audio_encoder)
-            gst_builder.run()
-    return sample_file
-
-
-def generateSamples(overwrite=False):
-    from timeside import __file__ as ts_file
-    ts_path = os.path.split(os.path.abspath(ts_file))[0]
-    tests_dir = os.path.abspath(os.path.join(ts_path, '../tests'))
-    if os.path.isdir(tests_dir):
-        samples_dir = os.path.abspath(os.path.join(tests_dir, 'samples'))
-        if not os.path.isdir(samples_dir):
-            os.makedirs(samples_dir)
-    else:
-        import tempfile
-        samples_dir = tempfile.mkdtemp(suffix="ts_samples")
-
-    samples = dict()
-
-    # --------- Sweeps ---------
-    # sweep 44100 mono wav
-    filename = 'sweep_mono.wav'
-    samplerate = 44100
-    gst_audio_encoder = 'wavenc'
-    sweep_mono = SweepArray(duration=8, samplerate=samplerate)
-    sample_file = generate_sample_file(filename, samples_dir,
-                                       gst_audio_encoder,
-                                       sample_array=sweep_mono,
-                                       overwrite=overwrite)
-    samples.update({filename: sample_file})
-
-    # sweep 44100 stereo wav
-    sweep_stereo = sweep_mono & sweep_mono
-    filename = 'sweep.wav'
-    gst_audio_encoder = 'wavenc'
-    sweep_mono = SweepArray(duration=8, samplerate=samplerate)
-    sample_file = generate_sample_file(filename, samples_dir,
-                                       gst_audio_encoder,
-                                       sample_array=sweep_stereo,
-                                       overwrite=overwrite)
-    samples.update({filename: sample_file})
-
-   # sweep 44100 stereo mp3
-    filename = 'sweep.mp3'
-    gst_audio_encoder = ['lamemp3enc', 'xingmux', 'id3v2mux']
-    sweep_mono = SweepArray(duration=8, samplerate=samplerate)
-    sample_file = generate_sample_file(filename, samples_dir,
-                                       gst_audio_encoder,
-                                       sample_array=sweep_stereo,
-                                       overwrite=overwrite)
-    samples.update({filename: sample_file})
-
-   # sweep 44100 stereo flac
-    filename = 'sweep.flac'
-    gst_audio_encoder = 'flacenc'
-    sweep_mono = SweepArray(duration=8, samplerate=samplerate)
-    sample_file = generate_sample_file(filename, samples_dir,
-                                       gst_audio_encoder,
-                                       sample_array=sweep_stereo,
-                                       overwrite=overwrite)
-    samples.update({filename: sample_file})
-
-   # sweep 44100 stereo ogg
-    filename = 'sweep.ogg'
-    gst_audio_encoder = ['vorbisenc', 'oggmux']
-    sweep_mono = SweepArray(duration=8, samplerate=samplerate)
-    sample_file = generate_sample_file(filename, samples_dir,
-                                       gst_audio_encoder,
-                                       sample_array=sweep_stereo,
-                                       overwrite=overwrite)
-    samples.update({filename: sample_file})
-
-    # sweep 32000 stereo wav
-    samplerate = 32000
-    sweep_mono = SweepArray(duration=8, samplerate=samplerate)
-    sweep_stereo = sweep_mono & sweep_mono
-
-    filename = 'sweep_32000.wav'
-    gst_audio_encoder = 'wavenc'
-    sweep_mono = SweepArray(duration=8, samplerate=samplerate)
-    sample_file = generate_sample_file(filename, samples_dir,
-                                       gst_audio_encoder,
-                                       sample_array=sweep_stereo,
-                                       overwrite=overwrite)
-    samples.update({filename: sample_file})
-
-    # --------- Sines ---------
-    # sine at 440Hz,  44100 mono wav
-    filename = 'sine440Hz_mono.wav'
-    samplerate = 44100
-    gst_audio_encoder = 'wavenc'
-    sweep_mono = SineArray(duration=8, samplerate=samplerate, frequency=440)
-    sample_file = generate_sample_file(filename, samples_dir,
-                                       gst_audio_encoder,
-                                       sample_array=sweep_mono,
-                                       overwrite=overwrite)
-    samples.update({filename: sample_file})
-
-    # Short 1s sine at 440Hz,  44100 mono wav
-    filename = 'sine440Hz_mono_1s.wav'
-    samplerate = 44100
-    gst_audio_encoder = 'wavenc'
-    sweep_mono = SineArray(duration=1, samplerate=samplerate, frequency=440)
-    sample_file = generate_sample_file(filename, samples_dir,
-                                       gst_audio_encoder,
-                                       sample_array=sweep_mono,
-                                       overwrite=overwrite)
-    samples.update({filename: sample_file})
-
-    # sine at 440Hz,  44100 stereo wav
-    filename = 'sine440Hz.wav'
-    sweep_stereo = sweep_mono & sweep_mono
-    gst_audio_encoder = 'wavenc'
-    sweep_mono = SineArray(duration=8, samplerate=samplerate, frequency=440)
-    sample_file = generate_sample_file(filename, samples_dir,
-                                       gst_audio_encoder,
-                                       sample_array=sweep_stereo,
-                                       overwrite=overwrite)
-    samples.update({filename: sample_file})
-
-    # sine at 440Hz,  44100 stereo mp3
-    filename = 'sine440Hz.mp3'
-    gst_audio_encoder = ['lamemp3enc', 'xingmux', 'id3v2mux']
-    sweep_mono = SineArray(duration=8, samplerate=samplerate, frequency=440)
-    sample_file = generate_sample_file(filename, samples_dir,
-                                       gst_audio_encoder,
-                                       sample_array=sweep_stereo,
-                                       overwrite=overwrite)
-    samples.update({filename: sample_file})
-
-    # sine at 440Hz,  44100 stereo ogg
-    filename = 'sine440Hz.ogg'
-    gst_audio_encoder = ['vorbisenc', 'oggmux']
-    sweep_mono = SineArray(duration=8, samplerate=samplerate, frequency=440)
-    sample_file = generate_sample_file(filename, samples_dir,
-                                       gst_audio_encoder,
-                                       sample_array=sweep_stereo,
-                                       overwrite=overwrite)
-    samples.update({filename: sample_file})
-
-    # --------- Equal tempered scale ---------
-    filename = 'C4_scale.wav'
-    samplerate = 44100
-    f_C4 = 261.63
-    f_D4 = 293.66
-    f_E4 = 329.63
-    f_F4 = 349.23
-    f_G4 = 392.00
-    f_A4 = 440.00
-    f_B4 = 493.88
-    f_C5 = 523.25
-    sineC4 = SineArray(duration=1, samplerate=samplerate, frequency=f_C4)
-    sineD4 = SineArray(duration=1, samplerate=samplerate, frequency=f_D4)
-    sineE4 = SineArray(duration=1, samplerate=samplerate, frequency=f_E4)
-    sineF4 = SineArray(duration=1, samplerate=samplerate, frequency=f_F4)
-    sineG4 = SineArray(duration=1, samplerate=samplerate, frequency=f_G4)
-    sineA4 = SineArray(duration=1, samplerate=samplerate, frequency=f_A4)
-    sineB4 = SineArray(duration=1, samplerate=samplerate, frequency=f_B4)
-    sineC5 = SineArray(duration=1, samplerate=samplerate, frequency=f_C5)
-
-    silence = SilenceArray(duration=0.2, samplerate=samplerate)
-
-    scale = (sineC4 + silence + sineD4 + silence + sineE4 + silence +
-             sineF4 + silence + sineG4 + silence + sineA4 + silence +
-             sineB4 + silence + sineC5)
-
-    gst_audio_encoder = 'wavenc'
-    sample_file = generate_sample_file(filename, samples_dir,
-                                       gst_audio_encoder,
-                                       sample_array=scale,
-                                       overwrite=overwrite)
-    samples.update({filename: sample_file})
-
-    # --------- White noise ---------
-    # white noise - 44100Hz mono
-    filename = 'white_noise_mono.wav'
-    samplerate = 44100
-    noise = WhiteNoiseArray(duration=8, samplerate=samplerate)
-    gst_audio_encoder = 'wavenc'
-    sample_file = generate_sample_file(filename, samples_dir,
-                                       gst_audio_encoder,
-                                       sample_array=noise,
-                                       overwrite=overwrite)
-    samples.update({filename: sample_file})
-
-    # white noise - 44100Hz stereo
-    filename = 'white_noise.wav'
-    samplerate = 44100
-    noise = WhiteNoiseArray(duration=8, samplerate=samplerate)
-    noise_stereo = noise & noise
-    gst_audio_encoder = 'wavenc'
-    sample_file = generate_sample_file(filename, samples_dir,
-                                       gst_audio_encoder,
-                                       sample_array=noise_stereo,
-                                       overwrite=overwrite)
-    samples.update({filename: sample_file})
-
-    # white noise - 32000Hz stereo
-    filename = 'white_noise_32000.wav'
-    samplerate = 32000
-    noise = WhiteNoiseArray(duration=8, samplerate=samplerate)
-    noise_stereo = noise & noise
-    gst_audio_encoder = 'wavenc'
-    sample_file = generate_sample_file(filename, samples_dir,
-                                       gst_audio_encoder,
-                                       sample_array=noise_stereo,
-                                       overwrite=overwrite)
-    samples.update({filename: sample_file})
-
-    return samples
-
-
-samples = generateSamples()
-
-
-if __name__ == '__main__':
-    generateSamples()