[SCM] python-pyo/master: New upstream release.

tiago at users.alioth.debian.org tiago at users.alioth.debian.org
Wed May 10 00:22:30 UTC 2017


The following commit has been merged in the master branch:
commit 34c253a8a952db98cfab531cbaebcdb3ada6718a
Author: Tiago Bortoletto Vaz <tiago at debian.org>
Date:   Thu Mar 2 11:11:21 2017 -0500

    New upstream release.

diff --git a/ChangeLog b/ChangeLog
index 9e0ab06..8ee28a6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,96 @@
+2017-02-13 belangeo <belangeo at gmail.com>
+
+    * Final revision for version 0.8.3.
+
+2017-02-13 belangeo <belangeo at gmail.com>
+
+    * Added new object: MidiDispatcher, self-contained midi dispatcher thread.
+      Updated MidiListener.
+
+2017-02-12 belangeo <belangeo at gmail.com>
+
+    * Upgraded version number to 0.8.3.
+
+2017-02-12 belangeo <belangeo at gmail.com>
+
+    * Prevents the creation of a SharedTable object on Windows (not implemented yet).
+
+2017-02-12 belangeo <belangeo at gmail.com>
+
+    * Fader and Adsr now start a new envelope from the current amplitude value
+      if the previous ramp has not finished yet.
+
+2017-02-12 belangeo <belangeo at gmail.com>
+
+    * Added new object: TableScan, Reads the content of a table in loop,
+      without interpolation.
+
+2017-02-11 belangeo <belangeo at gmail.com>
+
+    * Added setGlobalDur, setGlobalDel, getGlobalDur and getGlobalDel methods
+      to the Server object. These methods allow the user to manage starttime
+      and duration of audio objects globally.
+
+2017-02-09 belangeo <belangeo at gmail.com>
+
+    * Added shape argument to PVAmpMod and PVFreqMod objects. 
+      It allows to change the modulation oscillator's waveform.
+
+2017-02-08 belangeo <belangeo at gmail.com>
+
+    * Added onlyonce argument to Beat object.
+
+2017-02-08 belangeo <belangeo at gmail.com>
+
+    * Seq now accepts floating-point values as time units.
+
+2017-02-07 belangeo <belangeo at gmail.com>
+
+    * Added maxwindow argument to TableWrite. This is the maximum number of samples
+      over which the object is allowed to interpolate. Useful to avoid interpolation
+      over the entire table when using a circular writing pointer.
+
+2017-02-05 belangeo <belangeo at gmail.com>
+
+    * Added new object: TableFill, continuously fills a table with incoming samples.
+
+2017-02-04 belangeo <belangeo at gmail.com>
+
+    * Added onlyonce argument to Seq object.
+
+2017-01-30 belangeo <belangeo at gmail.com>
+
+    * Added new object: Particle2, An even more full control granular synthesis generator.
+
+2017-01-08 belangeo <belangeo at gmail.com>
+
+    * Added new object: SharedTable, an inter-process shared memory table.
+
+2017-01-07 belangeo <belangeo at gmail.com>
+
+    * Jack ports activation and auto-connection now happen in the boot process.
+
+2016-12-17 belangeo <belangeo at gmail.com>
+
+    * Upgraded version number to 0.8.2.
+
+2016-12-17 belangeo <belangeo at gmail.com>
+
+    * Fixed bug in Bendin value. Fixed midi input events handling. Set 
+      interpolation to off by default for midi continuous controllers.
+
+2016-12-17 belangeo <belangeo at gmail.com>
+
+    * E-Pyo: Fixed a bug in the documentation window.
+
+2016-12-17 belangeo <belangeo at gmail.com>
+
+    * TrigFunc and Pattern now accept tuple as arg argument (fixed issue #90).
+
+2016-12-15 belangeo <belangeo at gmail.com>
+
+    * Fixed portaudio suggested latency for realtime performance.
+
 2016-12-08 belangeo <belangeo at gmail.com>
 
     * Upgraded version number to 0.8.1.
@@ -1293,7 +1386,7 @@
 
 2011-07-22 belangeo <belangeo at gmail.com>
 
-    * Added new function : reducePoints(), apply a Douglas–Peucker curve reduction algorithm. 
+    * Added new function : reducePoints(), apply a Douglas–Peucker curve reduction algorithm. 
       Added loadRecFile() method to table objects.
     - rev 688
 
diff --git a/TODO.md b/TODO.md
index b213785..c5d2807 100644
--- a/TODO.md
+++ b/TODO.md
@@ -56,6 +56,9 @@ GUI
 
 - MixerGUI, an interface to control the routing of a Mixer object.
 
+- Keyboard, a virtual MIDI keyboard (adapted from Zyne's one).
+
+- Save item in ctrl() and DataTable graph() windows.
 
 Tables
 ------
diff --git a/debian/changelog b/debian/changelog
index 03b30b6..0760fae 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,15 @@
+python-pyo (0.8.3-1) unstable; urgency=medium
+
+  * New upstream release.
+
+ -- Tiago Bortoletto Vaz <tiago at debian.org>  Thu, 02 Mar 2017 11:08:16 -0500
+
+python-pyo (0.8.2-1) unstable; urgency=medium
+
+  * New upstream release.
+
+ -- Tiago Bortoletto Vaz <tiago at debian.org>  Sat, 17 Dec 2016 22:02:35 -0500
+
 python-pyo (0.8.1-1) unstable; urgency=medium
 
   * New upstream release.
diff --git a/debian/patches/series b/debian/patches/series
index 96b96c0..a2dcd10 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,2 +1,2 @@
 ePyo_paths.patch
-setup.patch
+setuphack.patch
diff --git a/debian/patches/setup.patch b/debian/patches/setuphack.patch
similarity index 95%
rename from debian/patches/setup.patch
rename to debian/patches/setuphack.patch
index ace104c..b3ce605 100644
--- a/debian/patches/setup.patch
+++ b/debian/patches/setuphack.patch
@@ -3,7 +3,7 @@
 @@ -23,7 +23,7 @@
  import os, sys, py_compile
  
- pyo_version = "0.8.1"
+ pyo_version = "0.8.2"
 -build_with_jack_support = False
 +build_with_jack_support = True
  compile_externals = False
@@ -38,7 +38,7 @@
 -    macros.append(('USE_JACK',None))
 -    ad_files.append("ad_jack.c")
 +#if '--use-jack' in sys.argv: 
-+#sys.argv.remove('--use-jack') 
++#    sys.argv.remove('--use-jack') 
 +build_with_jack_support = True
 +macros.append(('USE_JACK',None))
 +ad_files.append("ad_jack.c")
diff --git a/doc-sphinx/source/api/alphabetical.rst b/doc-sphinx/source/api/alphabetical.rst
index 34878f3..3863799 100644
--- a/doc-sphinx/source/api/alphabetical.rst
+++ b/doc-sphinx/source/api/alphabetical.rst
@@ -170,6 +170,7 @@ Alphabetical class reference
 - :py:class:`Pan` :     Cosinus panner with control on the spread factor.
 - :py:class:`ParaTable` :     Generates parabola window function.
 - :py:class:`PartialTable` :     Inharmonic waveform generator.
+- :py:class:`Particle2` :     An even more full control granular synthesis generator.
 - :py:class:`Particle` :     A full control granular synthesis generator.
 - :py:class:`Pattern` :     Periodically calls a Python function.
 - :py:class:`PeakAmp` :     Peak amplitude follower.
@@ -225,6 +226,7 @@ Alphabetical class reference
 - :py:class:`SfMarkerLooper` :     AIFF with markers soundfile looper.
 - :py:class:`SfMarkerShuffler` :     AIFF with markers soundfile shuffler.
 - :py:class:`SfPlayer` :     Soundfile player.
+- :py:class:`SharedTable` :     Create an inter-process shared memory table.
 - :py:class:`SigTo` :     Convert numeric value to PyoObject signal with portamento.
 - :py:class:`Sig` :     Convert numeric value to PyoObject signal.
 - :py:class:`Sin` :     Performs a sine function on audio signal.
@@ -240,12 +242,14 @@ Alphabetical class reference
 - :py:class:`SumOsc` :     Discrete summation formulae to produce complex spectra.
 - :py:class:`SuperSaw` :     Roland JP-8000 Supersaw emulator.
 - :py:class:`Switch` :     Audio switcher.
+- :py:class:`TableFill` :     Continuously fills a table with incoming samples.
 - :py:class:`TableIndex` :     Table reader by sample position without interpolation.
 - :py:class:`TableMorph` :     Morphs between multiple PyoTableObjects.
 - :py:class:`TablePut` :     Writes values, without repetitions, from an audio stream into a DataTable.
 - :py:class:`TableRead` :     Simple waveform table reader.
 - :py:class:`TableRec` :     TableRec is for writing samples into a previously created NewTable.
 - :py:class:`TableScale` :     Scales all the values contained in a PyoTableObject.
+- :py:class:`TableScan` :     Reads the content of a table in loop, without interpolation.
 - :py:class:`TableWrite` :     TableWrite writes samples into a previously created NewTable.
 - :py:class:`Tan` :     Performs a tangent function on audio signal.
 - :py:class:`Tanh` :     Performs a hyperbolic tangent function on audio signal.
diff --git a/doc-sphinx/source/api/classes/listener.rst b/doc-sphinx/source/api/classes/listener.rst
index c3406b6..d61ce3b 100644
--- a/doc-sphinx/source/api/classes/listener.rst
+++ b/doc-sphinx/source/api/classes/listener.rst
@@ -12,6 +12,12 @@ need to boot ands start an audio server before receiving messages.
 .. autoclass:: MidiListener
    :members:
 
+*MidiDispatcher*
+-----------------------------------
+
+.. autoclass:: MidiDispatcher
+   :members:
+
 *OscListener*
 -----------------------------------
 
diff --git a/doc-sphinx/source/api/classes/tableprocess.rst b/doc-sphinx/source/api/classes/tableprocess.rst
index 8e9da9e..25f7764 100644
--- a/doc-sphinx/source/api/classes/tableprocess.rst
+++ b/doc-sphinx/source/api/classes/tableprocess.rst
@@ -62,6 +62,12 @@ store audio samples or algorithmic sequences for future uses.
 .. autoclass:: Particle
    :members:
 
+*Particle2*
+-----------------------------------
+
+.. autoclass:: Particle2
+   :members:
+
 *Pointer*
 -----------------------------------
 
@@ -122,3 +128,14 @@ store audio samples or algorithmic sequences for future uses.
 .. autoclass:: TableScale
    :members:
 
+*TableFill*
+-----------------------------------
+
+.. autoclass:: TableFill
+   :members:
+
+*TableScan*
+-----------------------------------
+
+.. autoclass:: TableScan
+   :members:
diff --git a/doc-sphinx/source/api/classes/tables.rst b/doc-sphinx/source/api/classes/tables.rst
index 653f2dc..fdc9b79 100644
--- a/doc-sphinx/source/api/classes/tables.rst
+++ b/doc-sphinx/source/api/classes/tables.rst
@@ -125,3 +125,9 @@ in memory and access them quickly.
 
 .. autoclass:: PadSynthTable
    :members:
+
+*SharedTable*
+-----------------------------------
+
+.. autoclass:: SharedTable
+   :members:
diff --git a/doc-sphinx/source/index.rst b/doc-sphinx/source/index.rst
index c5223e6..1053c53 100644
--- a/doc-sphinx/source/index.rst
+++ b/doc-sphinx/source/index.rst
@@ -3,7 +3,7 @@
    You can adapt this file completely to your liking, but it should at least
    contain the root `toctree` directive.
 
-Welcome to the pyo 0.8.1 documentation
+Welcome to the pyo 0.8.3 documentation
 ===================================================
 
 .. image:: E-PyoIcon.png
diff --git a/doc-sphinx/source/perftips.rst b/doc-sphinx/source/perftips.rst
index ed66221..e52f048 100644
--- a/doc-sphinx/source/perftips.rst
+++ b/doc-sphinx/source/perftips.rst
@@ -42,34 +42,49 @@ sine wave computations to multiple processors.
     Spawning lot of sine waves to multiple processes.
     From the command line, run the script with -i flag.
 
+    Call quit() to stop the workers and quit the program.
+
     """
-    from pyo import *
+    import time
+    import multiprocessing
     from random import uniform
-    import time, multiprocessing
+    from pyo import Server, SineLoop
 
     class Group(multiprocessing.Process):
-        def __init__(self, n):
+        def __init__(self, num_of_sines):
             super(Group, self).__init__()
             self.daemon = True
+            self._terminated = False
+            self.num_of_sines = num_of_sines
 
-            self.s = Server()
-            self.s.deactivateMidi()
-            self.s.boot().start()
+        def run(self):
+            # All code that should run on a separated
+            # core must be created in the run() method.
+            self.server = Server()
+            self.server.deactivateMidi()
+            self.server.boot().start()
 
-            freqs = [uniform(400,800) for i in range(n)]
-            self.a = Sine(freq=freqs, mul=.005).out()
+            freqs = [uniform(400,800) for i in range(self.num_of_sines)]
+            self.oscs = SineLoop(freq=freqs, feedback=0.1, mul=.005).out()
 
-        def run(self):
-            while True:
+            # Keeps the process alive...
+            while not self._terminated:
                 time.sleep(0.001)
 
+            self.server.stop()
+
+        def stop(self):
+            self._terminated = True
+
     if __name__ == '__main__':
-        jobs = []
-        # Starts four processes playing 500 sines each.
-        for i in range(4):
-            jobs.append(Group(500))
-        for job in jobs:
-            job.start()
+        # Starts four processes playing 500 oscillators each.
+        jobs = [Group(500) for i in range(4)]
+        [job.start() for job in jobs]
+
+        def quit():
+            "Stops the workers and quit the program."
+            [job.stop() for job in jobs]
+            exit()
 
 Avoid memory allocation after initialization
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/embedded/puredata/pyo~-help.pd b/embedded/puredata/pyo~-help.pd
index ef4257d..730d8c2 100644
--- a/embedded/puredata/pyo~-help.pd
+++ b/embedded/puredata/pyo~-help.pd
@@ -234,7 +234,7 @@ in pyo~ inputs).;
 #N canvas 193 300 450 300 README 0;
 #X text 14 33 Author : Olivier Belanger;
 #X text 14 81 Last update : December 2016;
-#X text 14 57 Version : 0.8.1;
+#X text 14 57 Version : 0.8.2;
 #X text 15 108 pyo website : http://ajaxsoundstudio.com/software/pyo/
 ;
 #X text 15 10 pyo~ : Embedded pyo scripting inside puredata.;
diff --git a/include/pyomodule.h b/include/pyomodule.h
index c336f3e..ab23153 100644
--- a/include/pyomodule.h
+++ b/include/pyomodule.h
@@ -21,7 +21,7 @@
 #include "Python.h"
 #include <math.h>
 
-#define PYO_VERSION "0.8.1"
+#define PYO_VERSION "0.8.3"
 
 #ifndef __MYFLT_DEF
 #define __MYFLT_DEF
@@ -207,6 +207,7 @@
 
 #ifdef USE_PORTMIDI
 extern PyTypeObject MidiListenerType;
+extern PyTypeObject MidiDispatcherType;
 #endif
 #ifdef USE_OSC
 extern PyTypeObject OscListenerType;
@@ -500,12 +501,17 @@ extern PyTypeObject ScopeType;
 extern PyTypeObject PeakAmpType;
 extern PyTypeObject MainParticleType;
 extern PyTypeObject ParticleType;
+extern PyTypeObject MainParticle2Type;
+extern PyTypeObject Particle2Type;
 extern PyTypeObject AtanTableType;
 extern PyTypeObject RawMidiType;
 extern PyTypeObject ResampleType;
 extern PyTypeObject ExprType;
 extern PyTypeObject PadSynthTableType;
 extern PyTypeObject LogiMapType;
+extern PyTypeObject SharedTableType;
+extern PyTypeObject TableFillType;
+extern PyTypeObject TableScanType;
 
 /* Constants */
 #define E M_E
@@ -692,7 +698,7 @@ extern PyTypeObject LogiMapType;
     else if (self->interp == 3) \
         self->interp_func_ptr = cosine; \
     else if (self->interp == 4) \
-        self->interp_func_ptr = cubic; \
+        self->interp_func_ptr = cubic;
 
 /* Set data */
 #define SET_TABLE_DATA \
@@ -1567,6 +1573,8 @@ extern PyTypeObject LogiMapType;
 #define PLAY \
     float del = 0; \
     float dur = 0; \
+    float globdel = 0; \
+    float globdur = 0; \
     int nearestBuf = 0; \
     int i; \
  \
@@ -1575,6 +1583,14 @@ extern PyTypeObject LogiMapType;
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "|ff", kwlist, &dur, &del)) \
         return PyInt_FromLong(-1); \
  \
+    globdel = PyFloat_AsDouble(PyObject_CallMethod(PyServer_get_server(), "getGlobalDel", NULL)); \
+    globdur = PyFloat_AsDouble(PyObject_CallMethod(PyServer_get_server(), "getGlobalDur", NULL)); \
+ \
+    if (globdel != 0) \
+        del = globdel; \
+    if (globdur != 0) \
+        dur = globdur; \
+ \
     Stream_setStreamToDac(self->stream, 0); \
     if (del == 0) { \
         Stream_setBufferCountWait(self->stream, 0); \
@@ -1606,6 +1622,8 @@ extern PyTypeObject LogiMapType;
     int chnltmp = 0; \
     float del = 0; \
     float dur = 0; \
+    float globdel = 0; \
+    float globdur = 0; \
     int nearestBuf = 0; \
     int i; \
 \
@@ -1614,6 +1632,14 @@ extern PyTypeObject LogiMapType;
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "|iff", kwlist, &chnltmp, &dur, &del)) \
         return PyInt_FromLong(-1); \
  \
+    globdel = PyFloat_AsDouble(PyObject_CallMethod(PyServer_get_server(), "getGlobalDel", NULL)); \
+    globdur = PyFloat_AsDouble(PyObject_CallMethod(PyServer_get_server(), "getGlobalDur", NULL)); \
+ \
+    if (globdel != 0) \
+        del = globdel; \
+    if (globdur != 0) \
+        dur = globdur; \
+ \
     Stream_setStreamChnl(self->stream, chnltmp % self->nchnls); \
     Stream_setStreamToDac(self->stream, 1); \
     if (del == 0) { \
diff --git a/include/servermodule.h b/include/servermodule.h
index 2e2dd34..4b16f33 100644
--- a/include/servermodule.h
+++ b/include/servermodule.h
@@ -144,6 +144,10 @@ typedef struct {
     /* custom callback */
     PyObject *CALLBACK;
 
+    /* Globals dur and del times. */
+    float globalDur;
+    float globalDel;
+
     /* Properties */
     int verbosity; /* a sum of values to display different levels: 1 = error */
                    /* 2 = message, 4 = warning , 8 = debug. Default 7.*/
@@ -166,7 +170,7 @@ void Server_error(Server *self, char * format, ...);
 void Server_message(Server *self, char * format, ...);
 void Server_warning(Server *self, char * format, ...);
 void Server_debug(Server *self, char * format, ...);
-PyObject * Server_shut_down(Server *self);
+PyObject * Server_shutdown(Server *self);
 PyObject *Server_stop(Server *self);
 void Server_process_gui(Server *server);
 void Server_process_time(Server *server);
diff --git a/include/streammodule.h b/include/streammodule.h
index 78a8fa3..b19b0ce 100644
--- a/include/streammodule.h
+++ b/include/streammodule.h
@@ -56,9 +56,8 @@ extern PyTypeObject StreamType;
   (self) = (Stream *)(type)->tp_alloc((type), 0); \
   if ((self) == rt_error) { return rt_error; } \
  \
-  (self)->sid = (self)->chnl = (self)->todac = (self)->bufferCountWait = (self)->bufferCount = (self)->bufsize = (self)->duration = 0; \
-  (self)->active = 1;
-
+  (self)->sid = (self)->chnl = (self)->todac = (self)->bufferCountWait = 0; \
+  (self)->bufferCount = (self)->bufsize = (self)->duration = (self)->active = 0;
 
 typedef struct {
     PyObject_HEAD
diff --git a/installers/osx/PkgResources_x86_64_py2/ReadMe.rtf b/installers/osx/PkgResources_x86_64_py2/ReadMe.rtf
index daa1aed..79476ad 100755
--- a/installers/osx/PkgResources_x86_64_py2/ReadMe.rtf
+++ b/installers/osx/PkgResources_x86_64_py2/ReadMe.rtf
@@ -1,84 +1,97 @@
-{\rtf1\ansi\deff3\adeflang1025
-{\fonttbl{\f0\froman\fprq2\fcharset0 Times New Roman;}{\f1\froman\fprq2\fcharset2 Symbol;}{\f2\fswiss\fprq2\fcharset0 Arial;}{\f3\froman\fprq2\fcharset0 Liberation Serif{\*\falt Times New Roman};}{\f4\fswiss\fprq2\fcharset0 Liberation Sans{\*\falt Arial};}{\f5\froman\fprq2\fcharset0 LucidaGrande;}{\f6\fnil\fprq2\fcharset0 WenQuanYi Micro Hei;}{\f7\fnil\fprq2\fcharset0 FreeSans;}{\f8\fswiss\fprq0\fcharset128 FreeSans;}}
-{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}
-{\stylesheet{\s0\snext0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105 Normal;}
-{\s15\sbasedon0\snext16\sb240\sa120\keepn\dbch\af6\dbch\af7\afs28\loch\f4\fs28 Heading;}
-{\s16\sbasedon0\snext16\sl288\slmult1\sb0\sa140 Text Body;}
-{\s17\sbasedon16\snext17\sl288\slmult1\sb0\sa140\dbch\af8 List;}
-{\s18\sbasedon0\snext18\sb120\sa120\noline\i\dbch\af8\afs24\ai\fs24 Caption;}
-{\s19\sbasedon0\snext19\noline\dbch\af8 Index;}
-}{\*\generator LibreOffice/5.2.3.3$Linux_X86_64 LibreOffice_project/20m0$Build-3}{\info{\author Olivier }{\creatim\yr0\mo0\dy0\hr0\min0}{\revtim\yr2016\mo12\dy8\hr11\min16}{\printim\yr0\mo0\dy0\hr0\min0}}{\*\userprops}\deftab720
-\viewscale100
-{\*\pgdsctbl
-{\pgdsc0\pgdscuse451\pgwsxn12240\pghsxn15840\marglsxn1440\margrsxn1440\margtsxn1440\margbsxn1440\pgdscnxt0 Default Style;}}
-\formshade{\*\pgdscno0}\paperh15840\paperw12240\margl1440\margr1440\margt1440\margb1440\sectd\sbknone\sectunlocked1\pgndec\pgwsxn12240\pghsxn15840\marglsxn1440\margrsxn1440\margtsxn1440\margbsxn1440\ftnbj\ftnstart1\ftnrstcont\ftnnar\aenddoc\aftnrstcont\aftnstart1\aftnnrlc
-{\*\ftnsep}\pgndec\pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-Python-pyo (version 0.8.}{\cf1\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-1}{\cf1\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-) for python 2.7}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\cf1\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-System requirements : }{\cf1\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-macOS}{\cf1\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
- 10.8 to 10.12}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\cf1\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-This package installs all the required components to run pyo inside your current Python installation. Python 2.7 (32/64 bit) must be already installed on your system.}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\cf1\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-This package is divided into two separate installers. If you do not require one of them, please unselect the package in custom installation mode.}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\cf1\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-1. pyo extension:}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-The following components will be installed in the site-packages folder of the current Python Framework:}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-_pyo.so}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-_pyo64.so}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-pyo.py}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-pyo64.py}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-pyolib (folder)}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-2. Support libraries (i386 and x86_64):}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-This component will install a number of dynamic libraries on which pyo depends. If you already have these, then you can skip this installation.}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-Warning:}{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
- this installation will overwrite any previously installed libraries. These are the libraries that will be installed in your /usr/local/lib directory:}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-liblo.7.dylib}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-libportaudio.2.dylib}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-libportmidi.dylib}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-libsndfile.1.dylib}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-libFLAC.8.dylib}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-libvorbisenc.2.dylib}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-libvorbis.0.dylib}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-libogg.0.dylib}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-Olivier B\u233\'e9langer, 2016}
-\par }
\ No newline at end of file
+{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+{\fonttbl\f0\fnil\fcharset0 LucidaGrande;\f1\froman\fcharset0 Times-Roman;}
+{\colortbl;\red255\green255\blue255;}
+{\info
+{\author Olivier }}\margl1440\margr1440\vieww10800\viewh8400\viewkind0
+\deftab720
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardeftab720
+
+\f0\fs26 \cf0 Python-pyo (version 0.8.3) for python 2.7
+\f1\fs24 \
+
+\f0\fs26 \
+System requirements : macOS 10.6 to 10.12
+\f1\fs24 \
+
+\f0\fs26 \
+This package installs all the required components to run pyo inside your current Python installation. Python 2.7 (32/64 bit) must be already installed on your system.
+\f1\fs24 \
+
+\f0\fs26 \
+This package is divided into two separate installers. If you do not require one of them, please unselect the package in custom installation mode.
+\f1\fs24 \
+
+\f0\fs26 \
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardeftab720
+
+\b \cf0 1. pyo extension:
+\f1\b0\fs24 \
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardeftab720
+
+\f0\fs26 \cf0 The following components will be installed in the site-packages folder of the current Python Framework:
+\f1\fs24 \
+
+\f0\fs26 \
+_pyo.so
+\f1\fs24 \
+
+\f0\fs26 _pyo64.so
+\f1\fs24 \
+
+\f0\fs26 pyo.py
+\f1\fs24 \
+
+\f0\fs26 pyo64.py
+\f1\fs24 \
+
+\f0\fs26 pyolib (folder)
+\f1\fs24 \
+
+\f0\fs26 \
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardeftab720
+
+\b \cf0 2. Support libraries (i386 and x86_64):
+\f1\b0\fs24 \
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardeftab720
+
+\f0\fs26 \cf0 This component will install a number of dynamic libraries on which pyo depends. If you already have these, then you can skip this installation.
+\f1\fs24 \
+
+\f0\fs26 \
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardeftab720
+
+\b \cf0 Warning:
+\b0  this installation will overwrite any previously installed libraries. These are the libraries that will be installed in your /usr/local/lib directory:
+\f1\fs24 \
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardeftab720
+
+\f0\fs26 \cf0 \
+liblo.7.dylib
+\f1\fs24 \
+
+\f0\fs26 libportaudio.2.dylib
+\f1\fs24 \
+
+\f0\fs26 libportmidi.dylib
+\f1\fs24 \
+
+\f0\fs26 libsndfile.1.dylib
+\f1\fs24 \
+
+\f0\fs26 libFLAC.8.dylib
+\f1\fs24 \
+
+\f0\fs26 libvorbisenc.2.dylib
+\f1\fs24 \
+
+\f0\fs26 libvorbis.0.dylib
+\f1\fs24 \
+
+\f0\fs26 libogg.0.dylib
+\f1\fs24 \
+
+\f0\fs26 \
+\pard\pardeftab720
+\cf0 Olivier B\'e9langer, 2016
+\f1\fs24 \
+}
\ No newline at end of file
diff --git a/installers/osx/PkgResources_x86_64_py3/ReadMe.rtf b/installers/osx/PkgResources_x86_64_py3/ReadMe.rtf
index 1afd5e1..1a3f0e0 100755
--- a/installers/osx/PkgResources_x86_64_py3/ReadMe.rtf
+++ b/installers/osx/PkgResources_x86_64_py3/ReadMe.rtf
@@ -1,84 +1,97 @@
-{\rtf1\ansi\deff3\adeflang1025
-{\fonttbl{\f0\froman\fprq2\fcharset0 Times New Roman;}{\f1\froman\fprq2\fcharset2 Symbol;}{\f2\fswiss\fprq2\fcharset0 Arial;}{\f3\froman\fprq2\fcharset0 Liberation Serif{\*\falt Times New Roman};}{\f4\fswiss\fprq2\fcharset0 Liberation Sans{\*\falt Arial};}{\f5\froman\fprq2\fcharset0 LucidaGrande;}{\f6\fnil\fprq2\fcharset0 WenQuanYi Micro Hei;}{\f7\fnil\fprq2\fcharset0 FreeSans;}{\f8\fswiss\fprq0\fcharset128 FreeSans;}}
-{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}
-{\stylesheet{\s0\snext0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105 Normal;}
-{\s15\sbasedon0\snext16\sb240\sa120\keepn\dbch\af6\dbch\af7\afs28\loch\f4\fs28 Heading;}
-{\s16\sbasedon0\snext16\sl288\slmult1\sb0\sa140 Text Body;}
-{\s17\sbasedon16\snext17\sl288\slmult1\sb0\sa140\dbch\af8 List;}
-{\s18\sbasedon0\snext18\sb120\sa120\noline\i\dbch\af8\afs24\ai\fs24 Caption;}
-{\s19\sbasedon0\snext19\noline\dbch\af8 Index;}
-}{\*\generator LibreOffice/5.2.3.3$Linux_X86_64 LibreOffice_project/20m0$Build-3}{\info{\author Olivier }{\creatim\yr0\mo0\dy0\hr0\min0}{\revtim\yr2016\mo12\dy8\hr11\min17}{\printim\yr0\mo0\dy0\hr0\min0}}{\*\userprops}\deftab720
-\viewscale100
-{\*\pgdsctbl
-{\pgdsc0\pgdscuse451\pgwsxn12240\pghsxn15840\marglsxn1440\margrsxn1440\margtsxn1440\margbsxn1440\pgdscnxt0 Default Style;}}
-\formshade{\*\pgdscno0}\paperh15840\paperw12240\margl1440\margr1440\margt1440\margb1440\sectd\sbknone\sectunlocked1\pgndec\pgwsxn12240\pghsxn15840\marglsxn1440\margrsxn1440\margtsxn1440\margbsxn1440\ftnbj\ftnstart1\ftnrstcont\ftnnar\aenddoc\aftnrstcont\aftnstart1\aftnnrlc
-{\*\ftnsep}\pgndec\pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-Python-pyo (version 0.8.}{\cf1\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-1}{\cf1\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-) for python 3.5}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\cf1\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-System requirements : }{\cf1\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-macOS}{\cf1\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
- 10.8 to 10.12}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\cf1\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-This package installs all the required components to run pyo inside your current Python installation. Python 3.5 (32/64 bit) must be already installed on your system.}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\cf1\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-This package is divided into two separate installers. If you do not require one of them, please unselect the package in custom installation mode.}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\cf1\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-1. pyo extension:}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-The following components will be installed in the site-packages folder of the current Python Framework:}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-_pyo.cpython-35m-darwin.so}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-_pyo64.cpython-35m-darwin.so}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-pyo.py}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-pyo64.py}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-pyolib (folder)}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-2. Support libraries (i386 and x86_64):}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-This component will install a number of dynamic libraries on which pyo depends. If you already have these, then you can skip this installation.}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-Warning:}{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
- this installation will overwrite any previously installed libraries. These are the libraries that will be installed in your /usr/local/lib directory:}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-liblo.7.dylib}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-libportaudio.2.dylib}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-libportmidi.dylib}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-libsndfile.1.dylib}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-libFLAC.8.dylib}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-libvorbisenc.2.dylib}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-libvorbis.0.dylib}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-libogg.0.dylib}
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-
-\par \pard\plain \s0\nowidctlpar\hyphpar0\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\hich\af3\fs24\lang4105{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f5\hich\af5
-Olivier B\u233\'e9langer, 2016}
-\par }
\ No newline at end of file
+{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+{\fonttbl\f0\fnil\fcharset0 LucidaGrande;\f1\froman\fcharset0 Times-Roman;}
+{\colortbl;\red255\green255\blue255;}
+{\info
+{\author Olivier }}\margl1440\margr1440\vieww10800\viewh8400\viewkind0
+\deftab720
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardeftab720
+
+\f0\fs26 \cf0 Python-pyo (version 0.8.3) for python 3.5
+\f1\fs24 \
+
+\f0\fs26 \
+System requirements : macOS 10.8 to 10.12
+\f1\fs24 \
+
+\f0\fs26 \
+This package installs all the required components to run pyo inside your current Python installation. Python 3.5 (32/64 bit) must be already installed on your system.
+\f1\fs24 \
+
+\f0\fs26 \
+This package is divided into two separate installers. If you do not require one of them, please unselect the package in custom installation mode.
+\f1\fs24 \
+
+\f0\fs26 \
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardeftab720
+
+\b \cf0 1. pyo extension:
+\f1\b0\fs24 \
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardeftab720
+
+\f0\fs26 \cf0 The following components will be installed in the site-packages folder of the current Python Framework:
+\f1\fs24 \
+
+\f0\fs26 \
+_pyo.cpython-35m-darwin.so
+\f1\fs24 \
+
+\f0\fs26 _pyo64.cpython-35m-darwin.so
+\f1\fs24 \
+
+\f0\fs26 pyo.py
+\f1\fs24 \
+
+\f0\fs26 pyo64.py
+\f1\fs24 \
+
+\f0\fs26 pyolib (folder)
+\f1\fs24 \
+
+\f0\fs26 \
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardeftab720
+
+\b \cf0 2. Support libraries (i386 and x86_64):
+\f1\b0\fs24 \
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardeftab720
+
+\f0\fs26 \cf0 This component will install a number of dynamic libraries on which pyo depends. If you already have these, then you can skip this installation.
+\f1\fs24 \
+
+\f0\fs26 \
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardeftab720
+
+\b \cf0 Warning:
+\b0  this installation will overwrite any previously installed libraries. These are the libraries that will be installed in your /usr/local/lib directory:
+\f1\fs24 \
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardeftab720
+
+\f0\fs26 \cf0 \
+liblo.7.dylib
+\f1\fs24 \
+
+\f0\fs26 libportaudio.2.dylib
+\f1\fs24 \
+
+\f0\fs26 libportmidi.dylib
+\f1\fs24 \
+
+\f0\fs26 libsndfile.1.dylib
+\f1\fs24 \
+
+\f0\fs26 libFLAC.8.dylib
+\f1\fs24 \
+
+\f0\fs26 libvorbisenc.2.dylib
+\f1\fs24 \
+
+\f0\fs26 libvorbis.0.dylib
+\f1\fs24 \
+
+\f0\fs26 libogg.0.dylib
+\f1\fs24 \
+
+\f0\fs26 \
+\pard\pardeftab720
+\cf0 Olivier B\'e9langer, 2016
+\f1\fs24 \
+}
\ No newline at end of file
diff --git a/installers/osx/release_x86_64_py2.sh b/installers/osx/release_x86_64_py2.sh
index 0fec069..acf1b3f 100755
--- a/installers/osx/release_x86_64_py2.sh
+++ b/installers/osx/release_x86_64_py2.sh
@@ -8,9 +8,9 @@
 # 3. cd utils and build E-Pyo for python2
 # 4. cd installers/osx and build the release for python2
 
-export PACKAGE_NAME=pyo_0.8.1_x86_64_py2.pkg
-export DMG_DIR="pyo 0.8.1 py2 Universal"
-export DMG_NAME="pyo_0.8.1_OSX_py2-universal.dmg"
+export PACKAGE_NAME=pyo_0.8.3_x86_64_py2.pkg
+export DMG_DIR="pyo 0.8.3 py2 Universal"
+export DMG_NAME="pyo_0.8.3_OSX_py2-universal.dmg"
 export INSTALLER_DIR=`pwd`/installer
 export PYO_MODULE_DIR=$INSTALLER_DIR/PyoModule/Package_Contents/tmp
 export SUPPORT_LIBS_DIR=$INSTALLER_DIR/SupportLibs/Package_Contents/usr/local/lib
diff --git a/installers/osx/release_x86_64_py3.sh b/installers/osx/release_x86_64_py3.sh
index a7401a8..4abc0a7 100755
--- a/installers/osx/release_x86_64_py3.sh
+++ b/installers/osx/release_x86_64_py3.sh
@@ -8,9 +8,9 @@
 # 3. cd utils and build E-Pyo for python3
 # 4. cd installers/osx and build the release for python3
 
-export PACKAGE_NAME=pyo_0.8.1_x86_64_py3.pkg
-export DMG_DIR="pyo 0.8.1 py3 Universal"
-export DMG_NAME="pyo_0.8.1_OSX_py3-universal.dmg"
+export PACKAGE_NAME=pyo_0.8.3_x86_64_py3.pkg
+export DMG_DIR="pyo 0.8.3 py3 Universal"
+export DMG_NAME="pyo_0.8.3_OSX_py3-universal.dmg"
 export INSTALLER_DIR=`pwd`/installer
 export PYO_MODULE_DIR=$INSTALLER_DIR/PyoModule/Package_Contents/tmp
 export SUPPORT_LIBS_DIR=$INSTALLER_DIR/SupportLibs/Package_Contents/usr/local/lib
diff --git a/installers/win/win_installer_py27.iss b/installers/win/win_installer_py27.iss
index d34ab8a..a9eb776 100644
--- a/installers/win/win_installer_py27.iss
+++ b/installers/win/win_installer_py27.iss
@@ -3,7 +3,7 @@
 
 #define appName "pyo"
 #define pyVer "2.7"
-#define appVer "0.8.1"
+#define appVer "0.8.3"
 
 [Setup]
 ; NOTE: The value of AppId uniquely identifies this application.
diff --git a/installers/win/win_installer_py35.iss b/installers/win/win_installer_py35.iss
index 8962ee9..d95583e 100644
--- a/installers/win/win_installer_py35.iss
+++ b/installers/win/win_installer_py35.iss
@@ -3,7 +3,7 @@
 
 #define appName "pyo"
 #define pyVer "3.5"
-#define appVer "0.8.1"
+#define appVer "0.8.3"
 
 [Setup]
 ; NOTE: The value of AppId uniquely identifies this application.
diff --git a/pyo.py b/pyo.py
index 5791e4f..e93e6f2 100644
--- a/pyo.py
+++ b/pyo.py
@@ -94,7 +94,7 @@ OBJECTS_TREE = {
                                   'SquareTable', 'ChebyTable', 'CosTable', 
                                   'CurveTable', 'ExpTable', 'DataTable', 
                                   'WinTable', 'SincTable', 'PartialTable', 
-                                  'AtanTable', 'PadSynthTable']),
+                                  'AtanTable', 'PadSynthTable', 'SharedTable']),
         'PyoPVObject' : sorted(['PVAnal', 'PVSynth', 'PVTranspose', 'PVVerb', 
                                 'PVGate', 'PVAddSynth', 'PVCross', 'PVMult',
                                 'PVMorph', 'PVFilter', 'PVDelay', 'PVBuffer', 
@@ -143,7 +143,8 @@ OBJECTS_TREE = {
                                     'Granule', 'TableRead', 'TableMorph', 
                                     'Looper', 'TableIndex', 'OscBank', 'OscTrig',
                                     'TablePut', 'TableScale', 'Particle', 
-                                    'TableWrite']),
+                                     'Particle2', 'TableWrite', 'TableFill',
+                                     'TableScan']),
             'matrixprocess': sorted(['MatrixRec', 'MatrixPointer', 'MatrixMorph', 
                                      'MatrixRecLoop']),
             'triggers': sorted(['Metro', 'Beat', 'TrigEnv', 'TrigRand', 'Trig', 
@@ -168,6 +169,7 @@ OBJECTS_TREE = {
                                  'SLMapQ', 'SLMapDur', 'SLMapPan'])},
         'Server': [],
         'MidiListener': [],
+        'MidiDispatcher': [],
         'OscListener': [],
         'Stream': [],
         'TableStream': [],
diff --git a/pyolib/_core.py b/pyolib/_core.py
index acf8a70..447ae92 100644
--- a/pyolib/_core.py
+++ b/pyolib/_core.py
@@ -1,9 +1,13 @@
-# -*- coding: utf-8 -*-
+# encoding: utf-8
+"""
+This module defines the base classes for all objects in the library.
+
+"""
 from __future__ import division
 from __future__ import print_function
 from __future__ import absolute_import
 """
-Copyright 2009-2015 Olivier Belanger
+Copyright 2009-2016 Olivier Belanger
 
 This file is part of pyo, a python module to help digital signal
 processing script creation.
@@ -20,9 +24,13 @@ GNU Lesser General Public License for more details.
 
 You should have received a copy of the GNU Lesser General Public
 License along with pyo.  If not, see <http://www.gnu.org/licenses/>.
+
 """
-import types
-import random, os, sys, inspect, tempfile
+import os
+import sys
+import random
+import inspect
+import tempfile
 from subprocess import call
 from weakref import proxy
 
@@ -31,86 +39,88 @@ if sys.version_info[0] < 3:
     builtins = __builtin__
     bytes_t = str
     unicode_t = unicode
-    def tobytes(str, encoding=None):
-        return bytes(str)
+    def tobytes(strng, encoding=None):
+        "Convert unicode string to bytes."
+        return bytes(strng)
 else:
     import builtins
     bytes_t = bytes
     unicode_t = str
-    def tobytes(str, encoding="utf-8"):
-        return bytes(str, encoding=encoding)
+    def tobytes(strng, encoding="utf-8"):
+        "Convert unicode string to bytes."
+        return bytes(strng, encoding=encoding)
 
 if hasattr(builtins, 'pyo_use_double'):
-    import pyo64 as current_pyo
     from _pyo64 import *
+    import pyo64 as current_pyo
 else:
-    import pyo as current_pyo
     from _pyo import *
+    import pyo as current_pyo
 
-from ._maps import *
+from ._maps import SLMap, SLMapMul
 from ._widgets import createCtrlWindow
 from ._widgets import createViewTableWindow
 from ._widgets import createViewMatrixWindow
-    
+
 ######################################################################
 ### Utilities
 ######################################################################
 current_pyo_path = os.path.dirname(current_pyo.__file__)
 SNDS_PATH = os.path.join(current_pyo_path, "pyolib", "snds")
-XNOISE_DICT = {'uniform': 0, 'linear_min': 1, 'linear_max': 2, 'triangle': 3, 
-               'expon_min': 4, 'expon_max': 5, 'biexpon': 6, 'cauchy': 7, 
-               'weibull': 8, 'gaussian': 9, 'poisson': 10, 'walker': 11, 
+XNOISE_DICT = {'uniform': 0, 'linear_min': 1, 'linear_max': 2, 'triangle': 3,
+               'expon_min': 4, 'expon_max': 5, 'biexpon': 6, 'cauchy': 7,
+               'weibull': 8, 'gaussian': 9, 'poisson': 10, 'walker': 11,
                'loopseg': 12}
-FILE_FORMATS = {'wav': 0, 'wave': 0, 'aif': 1, 'aiff': 1, 'au': 2, '': 3, 
+FILE_FORMATS = {'wav': 0, 'wave': 0, 'aif': 1, 'aiff': 1, 'au': 2, '': 3,
                 'sd2': 4, 'flac': 5, 'caf': 6, 'ogg': 7}
 FUNCTIONS_INIT_LINES = {
-    "pa_count_host_apis": "pa_count_host_apis()", 
+    "pa_count_host_apis": "pa_count_host_apis()",
     "pa_list_host_apis": "pa_list_host_apis()",
-    "pa_get_default_host_api": "pa_get_default_host_api()", 
+    "pa_get_default_host_api": "pa_get_default_host_api()",
     "pa_count_devices": "pa_count_devices()",
-    "pa_list_devices": "pa_list_devices()", 
+    "pa_list_devices": "pa_list_devices()",
     "pa_get_devices_infos": "pa_get_devices_infos()",
-    "pa_get_version": "pa_get_version()", 
+    "pa_get_version": "pa_get_version()",
     "pa_get_version_text": "pa_get_version_text()",
-    "pa_get_input_devices": "pa_get_input_devices()", 
+    "pa_get_input_devices": "pa_get_input_devices()",
     "pa_get_output_devices": "pa_get_output_devices()",
-    "pa_get_default_input": "pa_get_default_input()", 
+    "pa_get_default_input": "pa_get_default_input()",
     "pa_get_default_output": "pa_get_default_output()",
-    "pa_get_input_max_channels": "pa_get_input_max_channels(x)", 
+    "pa_get_input_max_channels": "pa_get_input_max_channels(x)",
     "pa_get_output_max_channels": "pa_get_output_max_channels(x)",
-    "pm_get_default_output": "pm_get_default_output()", 
+    "pm_get_default_output": "pm_get_default_output()",
     "pm_get_default_input": "pm_get_default_input()",
-    "pm_get_output_devices": "pm_get_output_devices()", 
+    "pm_get_output_devices": "pm_get_output_devices()",
     "pm_get_input_devices": "pm_get_input_devices()",
-    "pm_list_devices": "pm_list_devices()", 
+    "pm_list_devices": "pm_list_devices()",
     "pm_count_devices": "pm_count_devices()",
-    "sndinfo": "sndinfo(path, print=False)", 
-    "savefile": 
-        "savefile(samples, path, sr=44100, channels=1, fileformat=0, sampletype=0)",
-    "savefileFromTable": 
-        "savefileFromTable(table, path, fileformat=0, sampletype=0)",
-    "upsamp": "upsamp(path, outfile, up=4, order=128)", 
+    "sndinfo": "sndinfo(path, print=False)",
+    "savefile": "savefile(samples, path, sr=44100, channels=1, "
+                "fileformat=0, sampletype=0)",
+    "savefileFromTable": "savefileFromTable(table, path, fileformat=0, "
+                         "sampletype=0)",
+    "upsamp": "upsamp(path, outfile, up=4, order=128)",
     "downsamp": "downsamp(path, outfile, down=4, order=128)",
-    "midiToHz": "midiToHz(x)", 
-    "hzToMidi": "hzToMidi(x)", 
-    "midiToTranspo": "midiToTranspo(x)", 
+    "midiToHz": "midiToHz(x)",
+    "hzToMidi": "hzToMidi(x)",
+    "midiToTranspo": "midiToTranspo(x)",
     "sampsToSec": "sampsToSec(x)",
-    "secToSamps": "secToSamps(x)", 
-    "linToCosCurve": 
-        "linToCosCurve(data, yrange=[0, 1], totaldur=1, points=1024, log=False)",
-    "rescale": 
-        "rescale(data, xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, xlog=False, ylog=False)",
-    "distanceToSegment": 
-        "distanceToSegment(p, p1, p2, xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, xlog=False, ylog=False)",
-    "reducePoints": "reducePoints(pointlist, tolerance=0.02)", 
-    "serverCreated": "serverCreated()", 
+    "secToSamps": "secToSamps(x)",
+    "linToCosCurve": "linToCosCurve(data, yrange=[0, 1], totaldur=1, "
+                     "points=1024, log=False)",
+    "rescale": "rescale(data, xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, "
+               "xlog=False, ylog=False)",
+    "distanceToSegment": "distanceToSegment(p, p1, p2, xmin=0.0, xmax=1.0, "
+                         "ymin=0.0, ymax=1.0, xlog=False, ylog=False)",
+    "reducePoints": "reducePoints(pointlist, tolerance=0.02)",
+    "serverCreated": "serverCreated()",
     "serverBooted": "serverBooted()",
-    "example": "example(cls, dur=5, toprint=True, double=False)", 
-    "class_args": "class_args(cls)", 
+    "example": "example(cls, dur=5, toprint=True, double=False)",
+    "class_args": "class_args(cls)",
     "getVersion": "getVersion()",
-    "convertStringToSysEncoding": "convertStringToSysEncoding(str)", 
+    "convertStringToSysEncoding": "convertStringToSysEncoding(str)",
     "convertArgsToLists": "convertArgsToLists(*args)",
-    "wrap": "wrap(arg, i)", 
+    "wrap": "wrap(arg, i)",
     "floatmap": "floatmap(x, min=0, max=1, exp=1)",
     "getPyoKeywords": "getPyoKeywords()"
 }
@@ -125,15 +135,19 @@ class PyoArgumentTypeError(PyoError):
     """Error raised when if an object got an invalid argument."""
 
 def isAudioObject(obj):
+    "Return True if the argument is an audio object."
     return isinstance(obj, PyoObject) or hasattr(obj, "stream")
 
 def isTableObject(obj):
+    "Return True if the argument is a table object."
     return isinstance(obj, PyoTableObject) or hasattr(obj, "tablestream")
 
 def isMatrixObject(obj):
+    "Return True if the argument is a matrix object."
     return isinstance(obj, PyoMatrixObject) or hasattr(obj, "matrixstream")
 
 def isPVObject(obj):
+    "Return True if the argument is a PV object."
     return isinstance(obj, PyoPVObject) or hasattr(obj, "pv_stream")
 
 def pyoArgsAssert(obj, format, *args):
@@ -183,28 +197,29 @@ def pyoArgsAssert(obj, format, *args):
         # Not used in Python 3, ignore it
         longType = None
 
+    i = 0
     expected = ""
-    for i in range(len(args)):
+    for i, arg in enumerate(args):
         f = format[i]
-        argtype = type(args[i])
+        argtype = type(arg)
         if f == "O":
-            if not isAudioObject(args[i]) and \
-                    argtype not in [list, int, longType, float]:
+            atypes = [list, int, longType, float]
+            if not isAudioObject(arg) and argtype not in atypes:
                 expected = "float or PyoObject"
         elif f == "o":
-            if not isAudioObject(args[i]) and argtype not in [list]:
+            if not isAudioObject(arg) and argtype not in [list]:
                 expected = "PyoObject"
         elif f == "T":
-            if not isTableObject(args[i]) and argtype not in [float, list]:
+            if not isTableObject(arg) and argtype not in [float, list]:
                 expected = "float or PyoTableObject"
         elif f == "t":
-            if not isTableObject(args[i]) and argtype not in [list]:
+            if not isTableObject(arg) and argtype not in [list]:
                 expected = "PyoTableObject"
         elif f == "m":
-            if not isMatrixObject(args[i]) and argtype not in [list]:
+            if not isMatrixObject(arg) and argtype not in [list]:
                 expected = "PyoMatrixObject"
         elif f == "p":
-            if not isPVObject(args[i]) and argtype not in [list]:
+            if not isPVObject(arg) and argtype not in [list]:
                 expected = "PyoPVObject"
         elif f == "n":
             if argtype not in [list, int, longType, float]:
@@ -249,10 +264,10 @@ def pyoArgsAssert(obj, format, *args):
             if argtype not in [list, tuple]:
                 expected = "list or tuple"
         elif f == "c":
-            if not callable(args[i]) and argtype not in [list, tuple, type(None)]:
+            if not callable(arg) and argtype not in [list, tuple, type(None)]:
                 expected = "callable"
         elif f == "C":
-            if not callable(args[i]) and argtype not in [type(None)]:
+            if not callable(arg) and argtype not in [type(None)]:
                 expected = "callable - list not allowed"
         elif f == "z":
             pass
@@ -265,7 +280,7 @@ def pyoArgsAssert(obj, format, *args):
         err = 'bad argument at position %d to "%s" (%s expected, got %s)'
         raise PyoArgumentTypeError(err % (i, name, expected, argtype))
 
-def convertStringToSysEncoding(str):
+def convertStringToSysEncoding(strng):
     """
     Convert a string to the current platform file system encoding.
 
@@ -273,14 +288,14 @@ def convertStringToSysEncoding(str):
 
     :Args:
 
-        str: string
+        strng: string
             String to convert.
 
     """
-    if type(str) not in [bytes_t, unicode_t]:
-        str = str.decode("utf-8")
-    str = str.encode(sys.getfilesystemencoding())
-    return str
+    if type(strng) not in [bytes_t, unicode_t]:
+        strng = strng.decode("utf-8")
+    strng = strng.encode(sys.getfilesystemencoding())
+    return strng
 
 def convertArgsToLists(*args):
     """
@@ -290,7 +305,7 @@ def convertArgsToLists(*args):
     """
     converted = []
     for i in args:
-        if isinstance(i, PyoObjectBase) or type(i) == list:
+        if isinstance(i, PyoObjectBase) or isinstance(i, list):
             converted.append(i)
         else:
             converted.append([i])
@@ -311,7 +326,7 @@ def wrap(arg, i):
 
 def example(cls, dur=5, toprint=True, double=False):
     """
-    Execute the example given in the documentation of the object as an argument.
+    Execute the documentation example of the object given as an argument.
 
     :Args:
 
@@ -332,7 +347,7 @@ def example(cls, dur=5, toprint=True, double=False):
     doc = cls.__doc__.splitlines()
     lines = []
     store = False
-    for i, line in enumerate(doc):
+    for line in doc:
         if not store:
             if ">>> s = Server" in line:
                 store = True
@@ -352,8 +367,10 @@ def example(cls, dur=5, toprint=True, double=False):
     else:
         ex = "import time\nfrom pyo import *\n"
     for line in ex_lines:
-        if ">>>" in line: line = line.lstrip(">>> ")
-        if "..." in line: line = "    " +  line.lstrip("... ")
+        if ">>>" in line:
+            line = line.lstrip(">>> ")
+        if "..." in line:
+            line = "    " +  line.lstrip("... ")
         ex += line + "\n"
 
     ex += "time.sleep(%f)\ns.stop()\ntime.sleep(0.25)\ns.shutdown()\n" % dur
@@ -365,10 +382,11 @@ def example(cls, dur=5, toprint=True, double=False):
     executable = sys.executable
     if not executable or executable is None:
         executable = "python"
-    p = call([executable, f.name])
+    call([executable, f.name])
 
 def removeExtraDecimals(x):
-    if type(x) == float:
+    "Return a floating-point value as a string with only two digits."
+    if isinstance(x, float):
         return "=%.2f" % x
     elif type(x) in [bytes_t, unicode_t]:
         return '="%s"' % x
@@ -394,8 +412,9 @@ def class_args(cls):
     name = cls.__name__
     try:
         # Try for a class __init__ function
-        arg, varargs, varkw, defaults = inspect.getargspec(getattr(cls, "__init__"))
-        arg = inspect.formatargspec(arg, varargs, varkw, defaults, 
+        init = getattr(cls, "__init__")
+        arg, varargs, varkw, defaults = inspect.getargspec(init)
+        arg = inspect.formatargspec(arg, varargs, varkw, defaults,
                                     formatvalue=removeExtraDecimals)
         arg = arg.replace("self, ", "")
         return name + arg
@@ -426,6 +445,7 @@ def getVersion():
     return (int(major), int(minor), int(rev))
 
 def getWeakMethodRef(x):
+    "Return a callable object as a weak method reference."
     if type(x) in [list, tuple]:
         tmp = []
         for y in x:
@@ -480,10 +500,10 @@ class PyoObjectBase(object):
         **Operations allowed on all PyoObjectBase**
 
         >>> len(obj)      # Return the number of streams managed by the object.
-        >>> obj[x]        # Return stream `x` of the object. 
+        >>> obj[x]        # Return stream `x` of the object.
         >>>               # `x` is a number from 0 to len(obj)-1.
         >>> dir(obj)      # Return the list of attributes of the object.
-        >>> for x in obj: # Can be used as an iterator (iterates over 
+        >>> for x in obj: # Can be used as an iterator (iterates over
         >>>               # object's audio streams).
 
     """
@@ -493,6 +513,8 @@ class PyoObjectBase(object):
     _STREAM_TYPE = ''
 
     def __init__(self):
+        self._base_objs = []
+        self._trig_objs = None
         self.__index = 0
         if not serverCreated():
             raise PyoServerStateException("You must create and boot a Server "
@@ -510,7 +532,7 @@ class PyoObjectBase(object):
 
         """
         attrs = dir(self)
-        pp =  '< Instance of %s class >' % self.__class__.__name__
+        pp = '< Instance of %s class >' % self.__class__.__name__
         pp += '\n-----------------------------'
         pp += '\nNumber of %s streams: %d' % (self._STREAM_TYPE, len(self))
         pp += '\n--- Attributes ---'
@@ -550,7 +572,7 @@ class PyoObjectBase(object):
     def __iter__(self):
         self.__index = 0
         return self
-    
+
     def __next__(self):
         if self.__index >= len(self):
             raise StopIteration
@@ -559,19 +581,22 @@ class PyoObjectBase(object):
         return x
 
     def next(self):
+        "Alias for __next__ method."
         # In Python 2.x, __next__() method is called next().
         return self.__next__()
 
     def __getitem__(self, i):
-        if i == 'trig': # not safe...
+        if i == 'trig':
             return self._trig_objs
         if type(i) == slice or i < len(self._base_objs):
             return self._base_objs[i]
         else:
             if type(i) in [bytes_t, unicode_t]:
-                print("Object %s has no stream named '%s'!" % (self.__class__.__name__, i))
+                args = (self.__class__.__name__, i)
+                print("Object %s has no stream named '%s'!" % args)
             else:
-                print("'i' too large in slicing %s object %s!" % (self._STREAM_TYPE, self.__class__.__name__))
+                args = (self._STREAM_TYPE, self.__class__.__name__)
+                print("'i' too large in slicing %s object %s!" % args)
 
     def __len__(self):
         return len(self._base_objs)
@@ -580,7 +605,8 @@ class PyoObjectBase(object):
         return '< Instance of %s class >' % self.__class__.__name__
 
     def __dir__(self):
-        args, varargs, varkw, defaults = inspect.getargspec(getattr(self.__class__, "__init__"))
+        init = getattr(self.__class__, "__init__")
+        args, _, _, _ = inspect.getargspec(init)
         args = [a for a in args if hasattr(self.__class__, a) and a != "self"]
         return args
 
@@ -610,7 +636,8 @@ class PyoObject(PyoObjectBase):
         between pyo objects or between pyo objects and numbers. Doing so
         returns a Dummy object with the result of the operation.
 
-        >>> # creates a Dummy object `b` with `mul` set to 0.5 and leave `a` unchanged.
+        >>> # Creates a Dummy object `b` with `mul` set to 0.5.
+        >>> # Leaves `a` unchanged.
         >>> b = a * 0.5
 
         Inplace multiplication, addition, division and substraction can be
@@ -619,7 +646,8 @@ class PyoObject(PyoObjectBase):
 
         >>> a *= 0.5 # replaces the `mul` attribute of `a`.
 
-        The next operators can be used with PyoObject (not with XXX_base objects).
+        The next operators can only be used with PyoObject, not with
+        XXX_base objects.
 
         **Exponent** and **modulo**
 
@@ -634,15 +662,16 @@ class PyoObject(PyoObjectBase):
 
         **Comparison operators**
 
-        >>> a < b # returns a Compare object created as: Compare(a, comp=b, mode="<")
-        >>> a <= b # returns a Compare object created as: Compare(a, comp=b, mode="<=")
-        >>> a == b # returns a Compare object created as: Compare(a, comp=b, mode="==")
-        >>> a != b # returns a Compare object created as: Compare(a, comp=b, mode="!=")
-        >>> a > b # returns a Compare object created as: Compare(a, comp=b, mode=">")
-        >>> a >= b # returns a Compare object created as: Compare(a, comp=b, mode=">=")
+        >>> # Comparison operators return a Compare object.
+        >>> x = a < b # same as: x = Compare(a, comp=b, mode="<")
+        >>> x = a <= b # same as: Compare(a, comp=b, mode="<=")
+        >>> x = a == b # same as: Compare(a, comp=b, mode="==")
+        >>> x = a != b # same as: Compare(a, comp=b, mode="!=")
+        >>> x = a > b # same as: Compare(a, comp=b, mode=">")
+        >>> x = a >= b # same as: Compare(a, comp=b, mode=">=")
 
-        A special case concerns the comparison of a PyoObject with None. All operators
-        return False except `a != None`, which returns True.
+        A special case concerns the comparison of a PyoObject with None.
+        All operators return False except `a != None`, which returns True.
 
     """
 
@@ -659,25 +688,30 @@ class PyoObject(PyoObjectBase):
         self._op_duplicate = 1
         self._map_list = []
         self._zeros = None
+        self._base_players = None
 
     def __add__(self, x):
         x, lmax = convertArgsToLists(x)
         if self.__len__() >= lmax:
-            _add_dummy = Dummy([obj + wrap(x,i//self._op_duplicate) for i, obj in enumerate(self._base_objs)])
+            _add_dummy = Dummy([obj + wrap(x, i//self._op_duplicate) \
+                                for i, obj in enumerate(self._base_objs)])
         else:
             if isinstance(x, PyoObject):
                 _add_dummy = x + self
             else:
-                _add_dummy = Dummy([wrap(self._base_objs,i) + obj for i, obj in enumerate(x)])
+                _add_dummy = Dummy([wrap(self._base_objs, i) + obj \
+                                    for i, obj in enumerate(x)])
         self._keep_trace.append(_add_dummy)
         return _add_dummy
 
     def __radd__(self, x):
         x, lmax = convertArgsToLists(x)
         if self.__len__() >= lmax:
-            _add_dummy = Dummy([obj + wrap(x,i//self._op_duplicate) for i, obj in enumerate(self._base_objs)])
+            _add_dummy = Dummy([obj + wrap(x, i//self._op_duplicate) \
+                                for i, obj in enumerate(self._base_objs)])
         else:
-            _add_dummy = Dummy([wrap(self._base_objs,i) + obj for i, obj in enumerate(x)])
+            _add_dummy = Dummy([wrap(self._base_objs, i) + obj \
+                                for i, obj in enumerate(x)])
         self._keep_trace.append(_add_dummy)
         return _add_dummy
 
@@ -688,12 +722,15 @@ class PyoObject(PyoObjectBase):
     def __sub__(self, x):
         x, lmax = convertArgsToLists(x)
         if self.__len__() >= lmax:
-            _add_dummy = Dummy([obj - wrap(x,i//self._op_duplicate) for i, obj in enumerate(self._base_objs)])
+            _add_dummy = Dummy([obj - wrap(x, i//self._op_duplicate) \
+                                for i, obj in enumerate(self._base_objs)])
         else:
             if isinstance(x, PyoObject):
-                _add_dummy = Dummy([wrap(self._base_objs,i) - wrap(x,i) for i in range(lmax)])
+                _add_dummy = Dummy([wrap(self._base_objs, i) - wrap(x, i) \
+                                    for i in range(lmax)])
             else:
-                _add_dummy = Dummy([wrap(self._base_objs,i) - obj for i, obj in enumerate(x)])
+                _add_dummy = Dummy([wrap(self._base_objs, i) - obj \
+                                    for i, obj in enumerate(x)])
         self._keep_trace.append(_add_dummy)
         return _add_dummy
 
@@ -711,7 +748,7 @@ class PyoObject(PyoObjectBase):
             for i, obj in enumerate(x):
                 sub_upsamp = Sig(obj)
                 self._keep_trace.append(sub_upsamp)
-                tmp.append(sub_upsamp - wrap(self._base_objs,i))
+                tmp.append(sub_upsamp - wrap(self._base_objs, i))
             _add_dummy = Dummy(tmp)
         self._keep_trace.append(_add_dummy)
         return _add_dummy
@@ -723,21 +760,25 @@ class PyoObject(PyoObjectBase):
     def __mul__(self, x):
         x, lmax = convertArgsToLists(x)
         if self.__len__() >= lmax:
-            _mul_dummy = Dummy([obj * wrap(x,i//self._op_duplicate) for i, obj in enumerate(self._base_objs)])
+            _mul_dummy = Dummy([obj * wrap(x, i//self._op_duplicate) \
+                                for i, obj in enumerate(self._base_objs)])
         else:
             if isinstance(x, PyoObject):
                 _mul_dummy = x * self
             else:
-                _mul_dummy = Dummy([wrap(self._base_objs,i) * obj for i, obj in enumerate(x)])
+                _mul_dummy = Dummy([wrap(self._base_objs, i) * obj \
+                                    for i, obj in enumerate(x)])
         self._keep_trace.append(_mul_dummy)
         return _mul_dummy
 
     def __rmul__(self, x):
         x, lmax = convertArgsToLists(x)
         if self.__len__() >= lmax:
-            _mul_dummy = Dummy([obj * wrap(x,i//self._op_duplicate) for i, obj in enumerate(self._base_objs)])
+            _mul_dummy = Dummy([obj * wrap(x, i//self._op_duplicate) \
+                                for i, obj in enumerate(self._base_objs)])
         else:
-            _mul_dummy = Dummy([wrap(self._base_objs,i) * obj for i, obj in enumerate(x)])
+            _mul_dummy = Dummy([wrap(self._base_objs, i) * obj \
+                                for i, obj in enumerate(x)])
         self._keep_trace.append(_mul_dummy)
         return _mul_dummy
 
@@ -757,12 +798,15 @@ class PyoObject(PyoObjectBase):
     def __div__(self, x):
         x, lmax = convertArgsToLists(x)
         if self.__len__() >= lmax:
-            _mul_dummy = Dummy([obj / wrap(x,i//self._op_duplicate) for i, obj in enumerate(self._base_objs)])
+            _mul_dummy = Dummy([obj / wrap(x, i//self._op_duplicate) \
+                                for i, obj in enumerate(self._base_objs)])
         else:
             if isinstance(x, PyoObject):
-                _mul_dummy = Dummy([wrap(self._base_objs,i) / wrap(x,i) for i in range(lmax)])
+                _mul_dummy = Dummy([wrap(self._base_objs, i) / wrap(x, i) \
+                                    for i in range(lmax)])
             else:
-                _mul_dummy = Dummy([wrap(self._base_objs,i) / obj for i, obj in enumerate(x)])
+                _mul_dummy = Dummy([wrap(self._base_objs, i) / obj \
+                                    for i, obj in enumerate(x)])
         self._keep_trace.append(_mul_dummy)
         return _mul_dummy
 
@@ -780,7 +824,7 @@ class PyoObject(PyoObjectBase):
             for i, obj in enumerate(x):
                 div_upsamp = Sig(obj)
                 self._keep_trace.append(div_upsamp)
-                tmp.append(div_upsamp / wrap(self._base_objs,i))
+                tmp.append(div_upsamp / wrap(self._base_objs, i))
             _mul_dummy = Dummy(tmp)
         self._keep_trace.append(_mul_dummy)
         return _mul_dummy
@@ -849,7 +893,10 @@ class PyoObject(PyoObjectBase):
 
     def isOutputting(self, all=False):
         """
-        Returns True if the object is sending samples to dac, otherwise, returns False.
+        Returns True if the object is outputting.
+
+        Returns True if the object is sending samples to dac,
+        otherwise, returns False.
 
         :Args:
 
@@ -905,24 +952,26 @@ class PyoObject(PyoObjectBase):
         :Args:
 
             dur: float, optional
-                Duration, in seconds, of the object's activation. The default is 0
-                and means infinite duration.
+                Duration, in seconds, of the object's activation. The default
+                is 0 and means infinite duration.
             delay: float, optional
                 Delay, in seconds, before the object's activation. Defaults to 0.
 
         """
         pyoArgsAssert(self, "nn", dur, delay)
         dur, delay, lmax = convertArgsToLists(dur, delay)
-        if hasattr(self, "_trig_objs"):
-            if type(self._trig_objs) == list:
+        if self._trig_objs is not None:
+            if isinstance(self._trig_objs, list):
                 for i in range(lmax):
                     for obj in self._trig_objs:
-                        obj.play(wrap(dur,i), wrap(delay,i))
+                        obj.play(wrap(dur, i), wrap(delay, i))
             else:
                 self._trig_objs.play(dur, delay)
-        if hasattr(self, "_base_players"):
-            [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._base_players)]
-        [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._base_objs)]
+        if self._base_players is not None:
+            [obj.play(wrap(dur, i), wrap(delay, i)) \
+             for i, obj in enumerate(self._base_players)]
+        [obj.play(wrap(dur, i), wrap(delay, i)) \
+         for i, obj in enumerate(self._base_objs)]
         return self
 
     def out(self, chnl=0, inc=1, dur=0, delay=0):
@@ -935,15 +984,16 @@ class PyoObject(PyoObjectBase):
         :Args:
 
             chnl: int, optional
-                Physical output assigned to the first audio stream of the object.
-                Defaults to 0.
+                Physical output assigned to the first audio stream of the
+                object. Defaults to 0.
             inc: int, optional
                 Output channel increment value. Defaults to 1.
             dur: float, optional
-                Duration, in seconds, of the object's activation. The default is 0
-                and means infinite duration.
+                Duration, in seconds, of the object's activation. The default
+                is 0 and means infinite duration.
             delay: float, optional
-                Delay, in seconds, before the object's activation. Defaults to 0.
+                Delay, in seconds, before the object's activation.
+                Defaults to 0.
 
         If `chnl` >= 0, successive streams increment the output number by
         `inc` and wrap around the global number of channels.
@@ -958,22 +1008,27 @@ class PyoObject(PyoObjectBase):
         """
         pyoArgsAssert(self, "iInn", chnl, inc, dur, delay)
         dur, delay, lmax = convertArgsToLists(dur, delay)
-        if hasattr(self, "_trig_objs"):
-            if type(self._trig_objs) == list:
+        if self._trig_objs is not None:
+            if isinstance(self._trig_objs, list):
                 for i in range(lmax):
                     for obj in self._trig_objs:
-                        obj.play(wrap(dur,i), wrap(delay,i))
+                        obj.play(wrap(dur, i), wrap(delay, i))
             else:
                 self._trig_objs.play(dur, delay)
-        if hasattr(self, "_base_players"):
-            [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._base_players)]
-        if type(chnl) == list:
-            [obj.out(wrap(chnl,i), wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._base_objs)]
+        if self._base_players is not None:
+            [obj.play(wrap(dur, i), wrap(delay, i))
+             for i, obj in enumerate(self._base_players)]
+        if isinstance(chnl, list):
+            [obj.out(wrap(chnl, i), wrap(dur, i), wrap(delay, i)) \
+             for i, obj in enumerate(self._base_objs)]
         else:
             if chnl < 0:
-                [obj.out(i*inc, wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(random.sample(self._base_objs, len(self._base_objs)))]
+                [obj.out(i*inc, wrap(dur, i), wrap(delay, i)) \
+                 for i, obj in enumerate(random.sample(self._base_objs,
+                                                       len(self._base_objs)))]
             else:
-                [obj.out(chnl+i*inc, wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._base_objs)]
+                [obj.out(chnl+i*inc, wrap(dur, i), wrap(delay, i)) \
+                 for i, obj in enumerate(self._base_objs)]
         return self
 
     def stop(self):
@@ -984,12 +1039,12 @@ class PyoObject(PyoObjectBase):
         creation.
 
         """
-        if hasattr(self, "_trig_objs"):
-            if type(self._trig_objs) == list:
+        if self._trig_objs is not None:
+            if isinstance(self._trig_objs, list):
                 [obj.stop() for obj in self._trig_objs]
             else:
                 self._trig_objs.stop()
-        if hasattr(self, "_base_players"):
+        if self._base_players is not None:
             [obj.stop() for obj in self._base_players]
         [obj.stop() for obj in self._base_objs]
         return self
@@ -1002,8 +1057,8 @@ class PyoObject(PyoObjectBase):
         :Args:
 
             voices: int, optional
-                Number of audio streams of the Mix object created by this method.
-                Defaults to 1.
+                Number of audio streams of the Mix object created by this
+                method. Defaults to 1.
 
                 If more than 1, object's streams are alternated and added into
                 Mix object's streams.
@@ -1034,8 +1089,8 @@ class PyoObject(PyoObjectBase):
         pyoArgsAssert(self, "nn", min, max)
         min, max, lmax = convertArgsToLists(min, max)
         if lmax > 1:
-            mul = [(wrap(max,i) - wrap(min,i)) * 0.5 for i in range(lmax)]
-            add = [(wrap(max,i) + wrap(min,i)) * 0.5 for i in range(lmax)]
+            mul = [(wrap(max, i) - wrap(min, i)) * 0.5 for i in range(lmax)]
+            add = [(wrap(max, i) + wrap(min, i)) * 0.5 for i in range(lmax)]
         else:
             mul = (max[0] - min[0]) * 0.5
             add = (max[0] + min[0]) * 0.5
@@ -1055,8 +1110,9 @@ class PyoObject(PyoObjectBase):
         """
         pyoArgsAssert(self, "O", x)
         self._mul = x
-        x, lmax = convertArgsToLists(x)
-        [obj.setMul(wrap(x,i//self._op_duplicate)) for i, obj in enumerate(self._base_objs)]
+        x, _ = convertArgsToLists(x)
+        [obj.setMul(wrap(x, i // self._op_duplicate)) \
+         for i, obj in enumerate(self._base_objs)]
 
     def setAdd(self, x):
         """
@@ -1070,8 +1126,9 @@ class PyoObject(PyoObjectBase):
         """
         pyoArgsAssert(self, "O", x)
         self._add = x
-        x, lmax = convertArgsToLists(x)
-        [obj.setAdd(wrap(x,i//self._op_duplicate)) for i, obj in enumerate(self._base_objs)]
+        x, _ = convertArgsToLists(x)
+        [obj.setAdd(wrap(x, i // self._op_duplicate)) \
+         for i, obj in enumerate(self._base_objs)]
 
     def setSub(self, x):
         """
@@ -1085,8 +1142,9 @@ class PyoObject(PyoObjectBase):
         """
         pyoArgsAssert(self, "O", x)
         self._add = x
-        x, lmax = convertArgsToLists(x)
-        [obj.setSub(wrap(x,i//self._op_duplicate)) for i, obj in enumerate(self._base_objs)]
+        x, _ = convertArgsToLists(x)
+        [obj.setSub(wrap(x, i // self._op_duplicate)) \
+         for i, obj in enumerate(self._base_objs)]
 
     def setDiv(self, x):
         """
@@ -1100,8 +1158,9 @@ class PyoObject(PyoObjectBase):
         """
         pyoArgsAssert(self, "O", x)
         self._mul = x
-        x, lmax = convertArgsToLists(x)
-        [obj.setDiv(wrap(x,i//self._op_duplicate)) for i, obj in enumerate(self._base_objs)]
+        x, _ = convertArgsToLists(x)
+        [obj.setDiv(wrap(x, i // self._op_duplicate)) \
+         for i, obj in enumerate(self._base_objs)]
 
     def set(self, attr, value, port=0.025, callback=None):
         """
@@ -1122,7 +1181,7 @@ class PyoObject(PyoObjectBase):
             callback: callable, optional
                 A python function to be called at the end of the ramp. If the
                 end of the ramp is not reached (ex.: called again before the
-                end of the portamento), the callback will not be called. 
+                end of the portamento), the callback will not be called.
 
         """
         pyoArgsAssert(self, "SnnC", attr, value, port, callback)
@@ -1134,7 +1193,8 @@ class PyoObject(PyoObjectBase):
                 if self._signal_dict[attr].isPlaying():
                     init = self._signal_dict[attr].get(True)
                     self._signal_dict[attr].stop()
-        self._signal_dict[attr] = VarPort(value, port, init, self._reset_from_set, attr)
+        self._signal_dict[attr] = VarPort(value, port, init,
+                                          self._reset_from_set, attr)
         setattr(self, attr, self._signal_dict[attr])
 
     def _reset_from_set(self, attr=None):
@@ -1173,7 +1233,8 @@ class PyoObject(PyoObjectBase):
         if map_list is None:
             map_list = self._map_list
         if map_list == []:
-            print(("There are no controls for %s object." % self.__class__.__name__))
+            clsname = self.__class__.__name__
+            print("There are no controls for %s object." % clsname)
             return
         createCtrlWindow(self, map_list, title, wxnoserver)
 
@@ -1182,14 +1243,16 @@ class PyoObject(PyoObjectBase):
         """float or PyoObject. Multiplication factor."""
         return self._mul
     @mul.setter
-    def mul(self, x): self.setMul(x)
+    def mul(self, x):
+        self.setMul(x)
 
     @property
     def add(self):
         """float or PyoObject. Addition factor."""
         return self._add
     @add.setter
-    def add(self, x): self.setAdd(x)
+    def add(self, x):
+        self.setAdd(x)
 
 ######################################################################
 ### PyoTableObject -> base class for pyo table objects
@@ -1207,7 +1270,8 @@ class PyoTableObject(PyoObjectBase):
     :Args:
 
         size: int
-            Length of the table in samples. Usually provided by the child object.
+            Length of the table in samples. Usually provided by the
+            child object.
 
     """
 
@@ -1332,16 +1396,18 @@ class PyoTableObject(PyoObjectBase):
         """
         Return a reference to the underlying object implementing the buffer protocol.
 
-        With the buffer protocol, a table can be referenced and modified, without
-        copying the data, with numpy functions. To create an array using the same
-        memory as the table:
+        With the buffer protocol, a table can be referenced and modified,
+        without copying the data, with numpy functions. To create an array
+        using the same memory as the table:
 
             t = SndTable(SNDS_PATH+"/transparent.aif")
             arr = numpy.asarray(t.getBuffer())
 
-        Now, every changes applied to the array will be reflected in the SndTable.
+        Now, every changes applied to the array will be reflected in
+        the SndTable.
 
-        For more details about the buffer protocol, see PEP 3118 and python documentation.
+        For more details about the buffer protocol, see PEP 3118 and
+        python documentation.
 
         """
         if chnl < 0 or chnl >= len(self):
@@ -1382,7 +1448,7 @@ class PyoTableObject(PyoObjectBase):
         if all:
             return [obj.getSize() for obj in self._base_objs]
         else:
-            if type(self._size) == list:
+            if isinstance(self._size, list):
                 return self._size[0]
             else:
                 return self._size
@@ -1409,7 +1475,7 @@ class PyoTableObject(PyoObjectBase):
 
     def get(self, pos):
         """
-        Returns the value, as float, stored at a specified position in the table.
+        Returns the value, as float, stored at a specific position in the table.
 
         If the object has more than 1 tablestream, the default is to
         return a list with the value of each tablestream. User can call
@@ -1423,8 +1489,10 @@ class PyoTableObject(PyoObjectBase):
         """
         pyoArgsAssert(self, "I", pos)
         values = [obj.get(pos) for obj in self._base_objs]
-        if len(values) == 1: return values[0]
-        else: return values
+        if len(values) == 1:
+            return values[0]
+        else:
+            return values
 
     def getTable(self, all=False):
         """
@@ -1591,14 +1659,14 @@ class PyoTableObject(PyoObjectBase):
 
         """
         pyoArgsAssert(self, "T", x)
-        if type(x) == list:
-            if type(x[0]) == list:
-                [obj.add(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+        if isinstance(x, list):
+            if isinstance(x[0], list):
+                [obj.add(wrap(x, i)) for i, obj in enumerate(self._base_objs)]
             else:
                 [obj.add(x) for obj in self._base_objs]
         else:
-            x, lmax = convertArgsToLists(x)
-            [obj.add(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+            x, _ = convertArgsToLists(x)
+            [obj.add(wrap(x, i)) for i, obj in enumerate(self._base_objs)]
         self.refreshView()
         return self
 
@@ -1616,14 +1684,14 @@ class PyoTableObject(PyoObjectBase):
 
         """
         pyoArgsAssert(self, "T", x)
-        if type(x) == list:
-            if type(x[0]) == list:
-                [obj.sub(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+        if isinstance(x, list):
+            if isinstance(x[0], list):
+                [obj.sub(wrap(x, i)) for i, obj in enumerate(self._base_objs)]
             else:
                 [obj.sub(x) for obj in self._base_objs]
         else:
-            x, lmax = convertArgsToLists(x)
-            [obj.sub(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+            x, _ = convertArgsToLists(x)
+            [obj.sub(wrap(x, i)) for i, obj in enumerate(self._base_objs)]
         self.refreshView()
         return self
 
@@ -1641,14 +1709,14 @@ class PyoTableObject(PyoObjectBase):
 
         """
         pyoArgsAssert(self, "T", x)
-        if type(x) == list:
-            if type(x[0]) == list:
-                [obj.mul(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+        if isinstance(x, list):
+            if isinstance(x[0], list):
+                [obj.mul(wrap(x, i)) for i, obj in enumerate(self._base_objs)]
             else:
                 [obj.mul(x) for obj in self._base_objs]
         else:
-            x, lmax = convertArgsToLists(x)
-            [obj.mul(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+            x, _ = convertArgsToLists(x)
+            [obj.mul(wrap(x, i)) for i, obj in enumerate(self._base_objs)]
         self.refreshView()
         return self
 
@@ -1674,7 +1742,8 @@ class PyoTableObject(PyoObjectBase):
 
         """
         pyoArgsAssert(self, "tIII", table, srcpos, destpos, length)
-        [obj.copyData(table[i], srcpos, destpos, length) for i, obj in enumerate(self._base_objs)]
+        [obj.copyData(table[i], srcpos,
+                      destpos, length) for i, obj in enumerate(self._base_objs)]
         self.refreshView()
 
     def rotate(self, pos):
@@ -1704,13 +1773,14 @@ class PyoTableObject(PyoObjectBase):
         args = [getattr(self, att) for att in self.__dir__()]
         if self.__class__.__name__ == "SndTable":
             _size = self.getSize()
-            if type(_size) != list:
+            if not isinstance(_size, list):
                 _size = [_size]
             _chnls = len(self._base_objs)
             args[0] = None
             args.append(_chnls)
             newtable = getattr(current_pyo, self.__class__.__name__)(*args)
-            [obj.setSize(_size[i%len(_size)]) for i, obj in enumerate(newtable.getBaseObjects())]
+            baseobjs = newtable.getBaseObjects()
+            [obj.setSize(_size[i%len(_size)]) for i, obj in enumerate(baseobjs)]
             [obj.copy(self[i]) for i, obj in enumerate(newtable.getBaseObjects())]
         else:
             newtable = getattr(current_pyo, self.__class__.__name__)(*args)
@@ -1734,8 +1804,9 @@ class PyoTableObject(PyoObjectBase):
 
         """
         pyoArgsAssert(self, "SB", title, wxnoserver)
-        samples = self._base_objs[0].getViewTable((500,200))
-        createViewTableWindow(samples, title, wxnoserver, self.__class__.__name__, self)
+        samples = self._base_objs[0].getViewTable((500, 200))
+        createViewTableWindow(samples, title, wxnoserver,
+                              self.__class__.__name__, self)
 
     def _setViewFrame(self, frame):
         self.viewFrame = frame
@@ -1743,6 +1814,10 @@ class PyoTableObject(PyoObjectBase):
     def _setGraphFrame(self, frame):
         self.graphFrame = frame
 
+    def _get_current_data(self):
+        # Thid method must be override by children.
+        return []
+
     def refreshView(self):
         """
         Updates the graphical display of the table, if applicable.
@@ -1767,7 +1842,8 @@ class PyoTableObject(PyoObjectBase):
         """int. Table size in samples."""
         return self._size
     @size.setter
-    def size(self, x): self.setSize(x)
+    def size(self, x):
+        self.setSize(x)
 
 ######################################################################
 ### PyoMatrixObject -> base class for pyo matrix objects
@@ -1788,6 +1864,7 @@ class PyoMatrixObject(PyoObjectBase):
     _STREAM_TYPE = 'matrix'
 
     def __init__(self):
+        self._size = (0, 0)
         PyoObjectBase.__init__(self)
         self.viewFrame = None
 
@@ -1915,8 +1992,10 @@ class PyoMatrixObject(PyoObjectBase):
         """
         pyoArgsAssert(self, "II", x, y)
         values = [obj.get(x, y) for obj in self._base_objs]
-        if len(values) == 1: return values[0]
-        else: return values
+        if len(values) == 1:
+            return values[0]
+        else:
+            return values
 
     def view(self, title="Matrix viewer", wxnoserver=False):
         """
@@ -1970,6 +2049,7 @@ class PyoPVObject(PyoObjectBase):
         self._target_dict = {}
         self._signal_dict = {}
         self._map_list = []
+        self._base_players = None
 
     def isPlaying(self, all=False):
         """
@@ -2002,19 +2082,22 @@ class PyoPVObject(PyoObjectBase):
         :Args:
 
             dur: float, optional
-                Duration, in seconds, of the object's activation. The default is 0
-                and means infinite duration.
+                Duration, in seconds, of the object's activation.
+                The default is 0 and means infinite duration.
             delay: float, optional
-                Delay, in seconds, before the object's activation. Defaults to 0.
+                Delay, in seconds, before the object's activation.
+                Defaults to 0.
 
         """
         pyoArgsAssert(self, "nn", dur, delay)
-        dur, delay, lmax = convertArgsToLists(dur, delay)
-        if hasattr(self, "_trig_objs"):
+        dur, delay, _ = convertArgsToLists(dur, delay)
+        if self._trig_objs is not None:
             self._trig_objs.play(dur, delay)
-        if hasattr(self, "_base_players"):
-            [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._base_players)]
-        [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._base_objs)]
+        if self._base_players is not None:
+            [obj.play(wrap(dur, i), wrap(delay, i)) \
+             for i, obj in enumerate(self._base_players)]
+        [obj.play(wrap(dur, i), wrap(delay, i)) \
+         for i, obj in enumerate(self._base_objs)]
         return self
 
     def stop(self):
@@ -2025,9 +2108,9 @@ class PyoPVObject(PyoObjectBase):
         creation.
 
         """
-        if hasattr(self, "_trig_objs"):
+        if self._trig_objs is not None:
             self._trig_objs.stop()
-        if hasattr(self, "_base_players"):
+        if self._base_players is not None:
             [obj.stop() for obj in self._base_players]
         [obj.stop() for obj in self._base_objs]
         return self
@@ -2058,7 +2141,8 @@ class PyoPVObject(PyoObjectBase):
                 if self._signal_dict[attr].isPlaying():
                     init = self._signal_dict[attr].get(True)
                     self._signal_dict[attr].stop()
-        self._signal_dict[attr] = VarPort(value, port, init, self._reset_from_set, attr)
+        self._signal_dict[attr] = VarPort(value, port, init,
+                                          self._reset_from_set, attr)
         setattr(self, attr, self._signal_dict[attr])
 
     def _reset_from_set(self, attr=None):
@@ -2094,7 +2178,8 @@ class PyoPVObject(PyoObjectBase):
         if map_list is None:
             map_list = self._map_list
         if map_list == []:
-            print(("There are no controls for %s object." % self.__class__.__name__))
+            clsname = self.__class__.__name__
+            print("There are no controls for %s object." % clsname)
             return
         createCtrlWindow(self, map_list, title, wxnoserver)
 
@@ -2144,7 +2229,7 @@ class Mix(PyoObject):
         PyoObject.__init__(self, mul, add)
         self._input = input
         mul, add, lmax = convertArgsToLists(mul, add)
-        if type(input) == list:
+        if isinstance(input, list):
             input_objs = []
             input_objs = [obj for pyoObj in input for obj in pyoObj.getBaseObjects()]
         else:
@@ -2165,7 +2250,9 @@ class Mix(PyoObject):
         for i in range(num):
             obj = input_objs[i % input_len]
             sub_lists[i % voices].append(obj)
-        self._base_objs = [Mix_base(l, wrap(mul,i), wrap(add,i)) for i, l in enumerate(sub_lists)]
+        self._base_objs = [Mix_base(l, wrap(mul, i),
+                                    wrap(add, i)) for i, l in enumerate(sub_lists)]
+        self.play()
 
 class Dummy(PyoObject):
     """
@@ -2248,7 +2335,8 @@ class InputFader(PyoObject):
         PyoObject.__init__(self)
         self._input = input
         input, lmax = convertArgsToLists(input)
-        self._base_objs = [InputFader_base(wrap(input,i)) for i in range(lmax)]
+        self._base_objs = [InputFader_base(wrap(input, i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -2264,15 +2352,17 @@ class InputFader(PyoObject):
         """
         pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
-        x, lmax = convertArgsToLists(x)
-        [obj.setInput(wrap(x,i), fadetime) for i, obj in enumerate(self._base_objs)]
+        x, _ = convertArgsToLists(x)
+        [obj.setInput(wrap(x, i),
+                      fadetime) for i, obj in enumerate(self._base_objs)]
 
     @property
     def input(self):
         """PyoObject. Input signal."""
         return self._input
     @input.setter
-    def input(self, x): self.setInput(x)
+    def input(self, x):
+        self.setInput(x)
 
 class Sig(PyoObject):
     """
@@ -2301,8 +2391,10 @@ class Sig(PyoObject):
         pyoArgsAssert(self, "OOO", value, mul, add)
         PyoObject.__init__(self, mul, add)
         self._value = value
-        value, mul ,add, lmax = convertArgsToLists(value, mul, add)
-        self._base_objs = [Sig_base(wrap(value,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        value, mul, add, lmax = convertArgsToLists(value, mul, add)
+        self._base_objs = [Sig_base(wrap(value, i), wrap(mul, i),
+                                    wrap(add, i)) for i in range(lmax)]
+        self.play()
 
     def setValue(self, x):
         """
@@ -2316,8 +2408,8 @@ class Sig(PyoObject):
         """
         pyoArgsAssert(self, "O", x)
         self._value = x
-        x, lmax = convertArgsToLists(x)
-        [obj.setValue(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+        x, _ = convertArgsToLists(x)
+        [obj.setValue(wrap(x, i)) for i, obj in enumerate(self._base_objs)]
 
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
         self._map_list = [SLMap(0, 1, "lin", "value", self._value)]
@@ -2328,7 +2420,8 @@ class Sig(PyoObject):
         """float or PyoObject. Numerical value to convert."""
         return self._value
     @value.setter
-    def value(self, x): self.setValue(x)
+    def value(self, x):
+        self.setValue(x)
 
 class VarPort(PyoObject):
     """
@@ -2357,7 +2450,8 @@ class VarPort(PyoObject):
 
     .. note::
 
-        The out() method is bypassed. VarPort's signal can not be sent to audio outs.
+        The out() method is bypassed. VarPort's signal can not be sent to
+        audio outs.
 
     >>> s = Server().boot()
     >>> s.start()
@@ -2369,14 +2463,19 @@ class VarPort(PyoObject):
     >>> a = SineLoop(freq=[fr,fr*1.01], feedback=0.05, mul=.2).out()
 
     """
-    def __init__(self, value, time=0.025, init=0.0, function=None, arg=None, mul=1, add=0):
+    def __init__(self, value, time=0.025, init=0.0, function=None, arg=None,
+                 mul=1, add=0):
         pyoArgsAssert(self, "nnnczOO", value, time, init, function, arg, mul, add)
         PyoObject.__init__(self, mul, add)
         self._value = value
         self._time = time
         self._function = getWeakMethodRef(function)
-        value, time, init, function, arg, mul ,add, lmax = convertArgsToLists(value, time, init, function, arg, mul, add)
-        self._base_objs = [VarPort_base(wrap(value,i), wrap(time,i), wrap(init,i), WeakMethod(wrap(function,i)), wrap(arg,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        value, time, init, function, arg, mul, add, lmax = convertArgsToLists(
+            value, time, init, function, arg, mul, add)
+        self._base_objs = [VarPort_base(wrap(value, i), wrap(time, i), wrap(init, i),
+                                        WeakMethod(wrap(function, i)), wrap(arg, i),
+                                        wrap(mul, i), wrap(add, i)) for i in range(lmax)]
+        self.play()
 
     def setValue(self, x):
         """
@@ -2390,8 +2489,8 @@ class VarPort(PyoObject):
         """
         pyoArgsAssert(self, "n", x)
         self._value = x
-        x, lmax = convertArgsToLists(x)
-        [obj.setValue(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+        x, _ = convertArgsToLists(x)
+        [obj.setValue(wrap(x, i)) for i, obj in enumerate(self._base_objs)]
 
     def setTime(self, x):
         """
@@ -2405,8 +2504,8 @@ class VarPort(PyoObject):
         """
         pyoArgsAssert(self, "n", x)
         self._time = x
-        x, lmax = convertArgsToLists(x)
-        [obj.setTime(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+        x, _ = convertArgsToLists(x)
+        [obj.setTime(wrap(x, i)) for i, obj in enumerate(self._base_objs)]
 
     def setFunction(self, x):
         """
@@ -2420,29 +2519,33 @@ class VarPort(PyoObject):
         """
         pyoArgsAssert(self, "c", x)
         self._function = getWeakMethodRef(x)
-        x, lmax = convertArgsToLists(x)
-        [obj.setFunction(WeakMethod(wrap(x,i))) for i, obj in enumerate(self._base_objs)]
+        x, _ = convertArgsToLists(x)
+        [obj.setFunction(WeakMethod(wrap(x, i))) \
+         for i, obj in enumerate(self._base_objs)]
 
     @property
     def value(self):
         """float. Numerical value to convert."""
         return self._value
     @value.setter
-    def value(self, x): self.setValue(x)
+    def value(self, x):
+        self.setValue(x)
 
     @property
     def time(self):
         """float. Ramp time."""
         return self._time
     @time.setter
-    def time(self, x): self.setTime(x)
+    def time(self, x):
+        self.setTime(x)
 
     @property
     def function(self):
         """Python callable. Function to be called."""
         return self._function
     @function.setter
-    def function(self, x): self.setFunction(x)
+    def function(self, x):
+        self.setFunction(x)
 
 class Pow(PyoObject):
     """
@@ -2471,7 +2574,9 @@ class Pow(PyoObject):
         self._base = base
         self._exponent = exponent
         base, exponent, mul, add, lmax = convertArgsToLists(base, exponent, mul, add)
-        self._base_objs = [M_Pow_base(wrap(base,i), wrap(exponent,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self._base_objs = [M_Pow_base(wrap(base, i), wrap(exponent, i),
+                                      wrap(mul, i), wrap(add, i)) for i in range(lmax)]
+        self.play()
 
     def setBase(self, x):
         """
@@ -2485,8 +2590,8 @@ class Pow(PyoObject):
         """
         pyoArgsAssert(self, "O", x)
         self._base = x
-        x, lmax = convertArgsToLists(x)
-        [obj.setBase(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+        x, _ = convertArgsToLists(x)
+        [obj.setBase(wrap(x, i)) for i, obj in enumerate(self._base_objs)]
 
     def setExponent(self, x):
         """
@@ -2500,22 +2605,24 @@ class Pow(PyoObject):
         """
         pyoArgsAssert(self, "O", x)
         self._exponent = x
-        x, lmax = convertArgsToLists(x)
-        [obj.setExponent(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+        x, _ = convertArgsToLists(x)
+        [obj.setExponent(wrap(x, i)) for i, obj in enumerate(self._base_objs)]
 
     @property
     def base(self):
         """float or PyoObject. Base composant."""
         return self._base
     @base.setter
-    def base(self, x): self.setBase(x)
+    def base(self, x):
+        self.setBase(x)
 
     @property
     def exponent(self):
         """float or PyoObject. Exponent composant."""
         return self._exponent
     @exponent.setter
-    def exponent(self, x): self.setExponent(x)
+    def exponent(self, x):
+        self.setExponent(x)
 
 class Wrap(PyoObject):
     """
@@ -2537,7 +2644,8 @@ class Wrap(PyoObject):
 
     .. note::
 
-        If `min` is higher than `max`, then the output will be the average of the two.
+        If `min` is higher than `max`, then the output will be the average
+        of the two.
 
     >>> s = Server().boot()
     >>> s.start()
@@ -2559,8 +2667,11 @@ class Wrap(PyoObject):
         self._min = min
         self._max = max
         self._in_fader = InputFader(input)
-        in_fader, min, max, mul, add, lmax = convertArgsToLists(self._in_fader, min, max, mul, add)
-        self._base_objs = [Wrap_base(wrap(in_fader,i), wrap(min,i), wrap(max,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        in_fader, min, max, mul, add, lmax = convertArgsToLists(
+            self._in_fader, min, max, mul, add)
+        self._base_objs = [Wrap_base(wrap(in_fader, i), wrap(min, i), wrap(max, i),
+                                     wrap(mul, i), wrap(add, i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -2590,8 +2701,8 @@ class Wrap(PyoObject):
         """
         pyoArgsAssert(self, "O", x)
         self._min = x
-        x, lmax = convertArgsToLists(x)
-        [obj.setMin(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+        x, _ = convertArgsToLists(x)
+        [obj.setMin(wrap(x, i)) for i, obj in enumerate(self._base_objs)]
 
     def setMax(self, x):
         """
@@ -2605,8 +2716,8 @@ class Wrap(PyoObject):
         """
         pyoArgsAssert(self, "O", x)
         self._max = x
-        x, lmax = convertArgsToLists(x)
-        [obj.setMax(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+        x, _ = convertArgsToLists(x)
+        [obj.setMax(wrap(x, i)) for i, obj in enumerate(self._base_objs)]
 
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
         self._map_list = [SLMap(0., 1., 'lin', 'min', self._min),
@@ -2619,21 +2730,24 @@ class Wrap(PyoObject):
         """PyoObject. Input signal to process."""
         return self._input
     @input.setter
-    def input(self, x): self.setInput(x)
+    def input(self, x):
+        self.setInput(x)
 
     @property
     def min(self):
         """float or PyoObject. Minimum possible value."""
         return self._min
     @min.setter
-    def min(self, x): self.setMin(x)
+    def min(self, x):
+        self.setMin(x)
 
     @property
     def max(self):
         """float or PyoObject. Maximum possible value."""
         return self._max
     @max.setter
-    def max(self, x): self.setMax(x)
+    def max(self, x):
+        self.setMax(x)
 
 class Compare(PyoObject):
     """
@@ -2672,8 +2786,14 @@ class Compare(PyoObject):
         self._mode = mode
         self._in_fader = InputFader(input)
         self.comp_dict = {"<": 0, "<=": 1, ">": 2, ">=": 3, "==": 4, "!=": 5}
-        in_fader, comp, mode, mul, add, lmax = convertArgsToLists(self._in_fader, comp, mode, mul, add)
-        self._base_objs = [Compare_base(wrap(in_fader,i), wrap(comp,i), self.comp_dict[wrap(mode,i)], wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        in_fader, comp, mode, mul, add, lmax = convertArgsToLists(
+            self._in_fader, comp, mode, mul, add)
+        self._base_objs = [Compare_base(wrap(in_fader, i),
+                                        wrap(comp, i),
+                                        self.comp_dict[wrap(mode, i)],
+                                        wrap(mul, i),
+                                        wrap(add, i)) for i in range(lmax)]
+        self.play()
 
     def out(self, chnl=0, inc=1, dur=0, delay=0):
         return self.play(dur, delay)
@@ -2706,8 +2826,8 @@ class Compare(PyoObject):
         """
         pyoArgsAssert(self, "O", x)
         self._comp = x
-        x, lmax = convertArgsToLists(x)
-        [obj.setComp(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+        x, _ = convertArgsToLists(x)
+        [obj.setComp(wrap(x, i)) for i, obj in enumerate(self._base_objs)]
 
     def setMode(self, x):
         """
@@ -2723,26 +2843,30 @@ class Compare(PyoObject):
         """
         pyoArgsAssert(self, "s", x)
         self._mode = x
-        x, lmax = convertArgsToLists(x)
-        [obj.setMode(self.comp_dict[wrap(x,i)]) for i, obj in enumerate(self._base_objs)]
+        x, _ = convertArgsToLists(x)
+        [obj.setMode(self.comp_dict[wrap(x, i)]) \
+         for i, obj in enumerate(self._base_objs)]
 
     @property
     def input(self):
         """PyoObject. Input signal."""
         return self._input
     @input.setter
-    def input(self, x): self.setInput(x)
+    def input(self, x):
+        self.setInput(x)
 
     @property
     def comp(self):
         """PyoObject. Comparison signal."""
         return self._comp
     @comp.setter
-    def comp(self, x): self.setComp(x)
+    def comp(self, x):
+        self.setComp(x)
 
     @property
     def mode(self):
         """string. Comparison operator."""
         return self._mode
     @mode.setter
-    def mode(self, x): self.setMode(x)
+    def mode(self, x):
+        self.setMode(x)
diff --git a/pyolib/_maps.py b/pyolib/_maps.py
index fe2bf70..d7ddd29 100644
--- a/pyolib/_maps.py
+++ b/pyolib/_maps.py
@@ -1,4 +1,4 @@
-# -*- coding: utf-8 -*-
+# encoding: utf-8
 """
 Copyright 2009-2015 Olivier Belanger
 
@@ -23,7 +23,7 @@ from math import pow, log10
 ######################################################################
 ### Map -> rescale values from sliders
 ######################################################################
-class Map:
+class Map(object):
     """
     Converts value between 0 and 1 on various scales.
 
@@ -53,8 +53,10 @@ class Map:
         Takes `x` between 0 and 1 and returns scaled value.
 
         """
-        if x < 0: x = 0.0
-        elif x > 1: x = 1.0
+        if x < 0:
+            x = 0.0
+        elif x > 1:
+            x = 1.0
 
         if self._scale == 'log':
             return pow(10, x * log10(self._max / self._min) + log10(self._min))
@@ -151,8 +153,8 @@ class SLMap(Map):
         name: string
             Name of the attributes the slider is affected to.
         init: int or float
-            Initial value. Specified in the real range, not between 0 and 1. Use
-            the `set` method to retreive the normalized corresponding value.
+            Initial value. Specified in the real range, not between 0 and 1.
+            Use `set` method to retreive the normalized corresponding value.
         res: string {'int', 'float'}, optional
             Sets the resolution of the slider. Defaults to 'float'.
         ramp: float, optional
@@ -166,14 +168,21 @@ class SLMap(Map):
     >>> s = Server().boot()
     >>> s.start()
     >>> ifs = [350,360,375,388]
-    >>> maps = [SLMap(20., 2000., 'log', 'freq', ifs), SLMap(0, 0.25, 'lin', 'feedback', 0), SLMapMul(.1)]
+    >>> slmapfreq = SLMap(20., 2000., 'log', 'freq', ifs)
+    >>> slmapfeed = SLMap(0, 0.25, 'lin', 'feedback', 0)
+    >>> maps = [slmapfreq, slmapfeed, SLMapMul(.1)]
     >>> a = SineLoop(freq=ifs, mul=.1).out()
     >>> a.ctrl(maps)
 
     """
-    def __init__(self, min, max, scale, name, init, res='float', ramp=0.025, dataOnly=False):
+    def __init__(self, min, max, scale, name, init, res='float', ramp=0.025,
+                 dataOnly=False):
         Map.__init__(self, min, max, scale)
-        self._name, self._init, self._res, self._ramp, self._dataOnly = name, init, res, ramp, dataOnly
+        self._name = name
+        self._init = init
+        self._res = res
+        self._ramp = ramp
+        self._dataOnly = dataOnly
 
     @property
     def name(self):
diff --git a/pyolib/_tkwidgets.py b/pyolib/_tkwidgets.py
index 84e5b2a..854a2a7 100644
--- a/pyolib/_tkwidgets.py
+++ b/pyolib/_tkwidgets.py
@@ -1,3 +1,8 @@
+# encoding: utf-8
+"""
+This module defines GUI widgets built with tkinter.
+
+"""
 from __future__ import division
 from __future__ import print_function
 from __future__ import absolute_import
@@ -20,11 +25,12 @@ GNU Lesser General Public License for more details.
 You should have received a copy of the GNU Lesser General Public
 License along with pyo.  If not, see <http://www.gnu.org/licenses/>.
 """
-import math, sys, os
+import math
+import sys
 if sys.version_info[0] < 3:
-    from Tkinter import *
+    import Tkinter as tk
 else:
-    from tkinter import *
+    import tkinter as tk
 
 # constants for platform displays with Tk
 if sys.platform.startswith('linux'):
@@ -40,32 +46,47 @@ else:
 ######################################################################
 ### Multisliders
 ######################################################################
-class MultiSlider(Frame):
-
+class MultiSlider(tk.Frame):
+    """
+    Draw multiple sliders on a canvas.
+
+    :Args:
+        master: tk.Frame
+            Parent frame.
+        init: list of floats
+            Initial values.
+        key: str
+            Name of the attribute to control.
+        command: callable
+            Function called with values as argument.
+
+    """
     def __init__(self, master, init, key, command):
-        Frame.__init__(self, master, bd=0, relief=FLAT)
+        tk.Frame.__init__(self, master, bd=0, relief=tk.FLAT)
         self._values = init
         self._nchnls = len(init)
         self._key = key
         self._command = command
         self._lines = []
         self._height = 16
-        self.canvas = Canvas(self, height=self._height*self._nchnls+1,
-                            width=225, relief=FLAT, bd=0, bg="#BCBCAA")
+        self.canvas = tk.Canvas(self, height=self._height*self._nchnls+1,
+                                width=225, relief=tk.FLAT, bd=0, bg="#BCBCAA")
         w = self.canvas.winfo_width()
         for i in range(self._nchnls):
             x = int(self._values[i] * w)
             y = self._height * i + Y_OFFSET
-            self._lines.append(self.canvas.create_rectangle(0, y, x,
-                                y+self._height-1, width=0, fill="#121212"))
+            rect = self.canvas.create_rectangle(0, y, x, y+self._height-1,
+                                                width=0, fill="#121212")
+            self._lines.append(rect)
         self.canvas.bind("<Button-1>", self.clicked)
         self.canvas.bind("<Motion>", self.move)
         self.canvas.bind("<Configure>", self.size)
-        self.canvas.grid(sticky=E+W)
+        self.canvas.grid(sticky=tk.E + tk.W)
         self.columnconfigure(0, weight=1)
         self.grid()
 
     def size(self, event):
+        "Method called when resizing the window."
         w = self.canvas.winfo_width()
         for i in range(len(self._lines)):
             y = self._height * i + Y_OFFSET
@@ -73,15 +94,18 @@ class MultiSlider(Frame):
             self.canvas.coords(self._lines[i], 0, y, x, y+self._height-1)
 
     def clicked(self, event):
+        "Method called when clicking on the window."
         self.update(event)
 
     def move(self, event):
+        "Method called on left mouse moion."
         if event.state == 0x0100:
             slide = (event.y - Y_OFFSET) // self._height
             if 0 <= slide < len(self._lines):
                 self.update(event)
 
     def update(self, event):
+        "Update and send current values."
         w = self.canvas.winfo_width()
         slide = (event.y - Y_OFFSET) // self._height
         val = event.x / float(w)
@@ -93,8 +117,8 @@ class MultiSlider(Frame):
 ######################################################################
 ### Control window for PyoObject
 ######################################################################
-class Command:
-
+class Command(object):
+    "Command event used to control a slider value."
     def __init__(self, func, key):
         self.func = func
         self.key = key
@@ -102,10 +126,21 @@ class Command:
     def __call__(self, value):
         self.func(self.key, value)
 
-class PyoObjectControl(Frame):
+class PyoObjectControl(tk.Frame):
+    """
+    Create a slider/multislider control window.
 
+    :Args:
+        master: tk.Frame
+            Parent frame.
+        obj: PyoObjectBase
+            The object to control attributes.
+        map_list: list of SLMap
+            The list of attribute definitions.
+
+    """
     def __init__(self, master=None, obj=None, map_list=None):
-        Frame.__init__(self, master, bd=1, relief=GROOVE)
+        tk.Frame.__init__(self, master, bd=1, relief=tk.GROOVE)
         from .controls import SigTo
         self.bind('<Destroy>', self._destroy)
         self._obj = obj
@@ -124,25 +159,32 @@ class PyoObjectControl(Frame):
             else:
                 self._maps[key] = m
                 # label (param name)
-                label = Label(self, height=1, width=10, highlightthickness=0, text=key)
+                label = tk.Label(self, height=1, width=10, highlightthickness=0,
+                                 text=key)
                 label.grid(row=i, column=0)
                 # create and pack slider
-                if type(init) != list:
-                    self._sliders.append(Scale(self, command=Command(self.setval, key),
-                                  orient=HORIZONTAL, relief=GROOVE, from_=0., to=1., showvalue=False,
-                                  resolution=.0001, bd=1, length=225, troughcolor="#BCBCAA", width=12))
+                if not isinstance(init, list):
+                    slider = tk.Scale(self, command=Command(self.setval, key),
+                                      orient=tk.HORIZONTAL, relief=tk.GROOVE,
+                                      from_=0., to=1., showvalue=False,
+                                      resolution=.0001, bd=1, length=225,
+                                      troughcolor="#BCBCAA", width=12)
+                    self._sliders.append(slider)
                     self._sliders[-1].set(m.set(init))
                     disp_height = 1
                 else:
-                    self._sliders.append(MultiSlider(self, [m.set(x) for x in init], key, self.setval))
+                    self._sliders.append(MultiSlider(self,
+                                                     [m.set(x) for x in init],
+                                                     key, self.setval))
                     disp_height = len(init)
-                self._sliders[-1].grid(row=i, column=1, sticky=E+W)
+                self._sliders[-1].grid(row=i, column=1, sticky=tk.E + tk.W)
                 # display of numeric values
-                textvar = StringVar(self)
-                display = Label(self, height=disp_height, width=10, highlightthickness=0, textvariable=textvar)
+                textvar = tk.StringVar(self)
+                display = tk.Label(self, height=disp_height, width=10,
+                                   highlightthickness=0, textvariable=textvar)
                 display.grid(row=i, column=2)
                 self._displays[key] = textvar
-                if type(init) != list:
+                if not isinstance(init, list):
                     self._displays[key].set("%.4f" % init)
                 else:
                     self._displays[key].set("\n".join(["%.4f" % i for i in init]))
@@ -159,7 +201,7 @@ class PyoObjectControl(Frame):
         top.rowconfigure(0, weight=1)
         top.columnconfigure(0, weight=1)
         self.columnconfigure(1, weight=1)
-        self.grid(ipadx=5, ipady=5, sticky=E+W)
+        self.grid(ipadx=5, ipady=5, sticky=tk.E + tk.W)
 
     def _destroy(self, event):
         for m in self._map_list:
@@ -169,7 +211,8 @@ class PyoObjectControl(Frame):
                 del self._sigs[key]
 
     def setval(self, key, x):
-        if type(x) != list:
+        "Set a new value 'x' to attribute 'key'."
+        if not isinstance(x, list):
             value = self._maps[key].get(float(x))
             self._displays[key].set("%.4f" % value)
         else:
@@ -182,15 +225,18 @@ class PyoObjectControl(Frame):
 ######################################################################
 ### View window for PyoTableObject
 ######################################################################
-class ViewTable(Frame):
-
+class ViewTable(tk.Frame):
+    "PyoTableObject display."
     def __init__(self, master=None, samples=None):
-        Frame.__init__(self, master, bd=1, relief=GROOVE)
+        tk.Frame.__init__(self, master, bd=1, relief=tk.GROOVE)
         self.width = 500
         self.height = 200
         self.half_height = self.height // 2
-        self.canvas = Canvas(self, height=self.height, width=self.width, relief=SUNKEN, bd=1, bg="#EFEFEF")
-        self.canvas.create_line(0, self.half_height+Y_OFFSET, self.width, self.half_height+Y_OFFSET, fill='grey', dash=(4,2))
+        self.canvas = tk.Canvas(self, height=self.height, width=self.width,
+                                relief=tk.SUNKEN, bd=1, bg="#EFEFEF")
+        self.canvas.create_line(0, self.half_height+Y_OFFSET, self.width,
+                                self.half_height+Y_OFFSET, fill='grey',
+                                dash=(4, 2))
         self.canvas.create_line(*samples)
         self.canvas.grid()
         self.grid(ipadx=10, ipady=10)
@@ -198,13 +244,14 @@ class ViewTable(Frame):
 ######################################################################
 ## View window for PyoMatrixObject
 #####################################################################
-class ViewMatrix(Frame):
-
+class ViewMatrix(tk.Frame):
+    "PyoMatrixObject display."
     def __init__(self, master=None, samples=None, size=None):
-        Frame.__init__(self, master, bd=1, relief=GROOVE)
+        tk.Frame.__init__(self, master, bd=1, relief=tk.GROOVE)
         self.width = size[0]
         self.height = size[1]
-        self.canvas = Canvas(self, width=self.width, height=self.height, relief=SUNKEN, bd=1, bg="#EFEFEF")
+        self.canvas = tk.Canvas(self, width=self.width, height=self.height,
+                                relief=tk.SUNKEN, bd=1, bg="#EFEFEF")
         for i in range(self.width*self.height):
             x = i % self.width
             y = i // self.width
@@ -224,11 +271,12 @@ class ViewMatrix(Frame):
 ######################################################################
 ### Server Object User Interface (Tk)
 ######################################################################
-class ServerGUI(Frame):
-
-    def __init__(self, master=None, nchnls=2, startf=None, stopf=None, recstartf=None,
-                recstopf=None, ampf=None, started=0, locals=None, shutdown=None, meter=True, timer=True, amp=1.):
-        Frame.__init__(self, master, padx=10, pady=10, bd=2, relief=GROOVE)
+class ServerGUI(tk.Frame):
+    "Server's graphical interface."
+    def __init__(self, master=None, nchnls=2, startf=None, stopf=None,
+                 recstartf=None, recstopf=None, ampf=None, started=0,
+                 locals=None, shutdown=None, meter=True, timer=True, amp=1.):
+        tk.Frame.__init__(self, master, padx=10, pady=10, bd=2, relief=tk.GROOVE)
         self.shutdown = shutdown
         self.locals = locals
         self.meter = meter
@@ -254,67 +302,84 @@ class ServerGUI(Frame):
             self.start(True)
 
     def createWidgets(self):
+        "Interface builder."
         row = 0
-        self.startStringVar = StringVar(self)
+        self.startStringVar = tk.StringVar(self)
         self.startStringVar.set('Start')
-        self.startButton = Button(self, textvariable=self.startStringVar, command=self.start)
+        self.startButton = tk.Button(self, textvariable=self.startStringVar,
+                                     command=self.start)
         self.startButton.grid(ipadx=5)
 
-        self.recStringVar = StringVar(self)
+        self.recStringVar = tk.StringVar(self)
         self.recStringVar.set('Rec Start')
-        self.recButton = Button(self, textvariable=self.recStringVar, command=self.record)
+        self.recButton = tk.Button(self, textvariable=self.recStringVar,
+                                   command=self.record)
         self.recButton.grid(ipadx=5, row=row, column=1)
 
-        self.quitButton = Button(self, text='Quit', command=self.on_quit)
+        self.quitButton = tk.Button(self, text='Quit', command=self.on_quit)
         self.quitButton.grid(ipadx=5, row=row, column=2)
         row += 1
 
-        self.ampScale = Scale(self, command=self.setAmp, digits=4, label='Amplitude (dB)',
-                              orient=HORIZONTAL, relief=GROOVE, from_=-60.0, to=18.0,
-                              resolution=.01, bd=1, length=250, troughcolor="#BCBCAA", width=10)
+        self.ampScale = tk.Scale(self, command=self.setAmp, digits=4,
+                                 label='Amplitude (dB)', orient=tk.HORIZONTAL,
+                                 relief=tk.GROOVE, from_=-60.0, to=18.0,
+                                 resolution=.01, bd=1, length=250,
+                                 troughcolor="#BCBCAA", width=10)
         self.ampScale.set(20.0 * math.log10(self.amp))
         self.ampScale.grid(ipadx=5, ipady=5, row=row, column=0, columnspan=3)
         row += 1
 
         if self.meter:
-            self.vumeter = Canvas(self, height=5*self.nchnls+1, width=250, relief=FLAT, bd=0, bg="#323232")
+            self.vumeter = tk.Canvas(self, height=5*self.nchnls+1, width=250,
+                                     relief=tk.FLAT, bd=0, bg="#323232")
             self.green = []
             self.yellow = []
             self.red = []
             for i in range(self.nchnls):
                 y = 5 * (i + 1) + 1 - VM_OFFSET
-                self.green.append(self.vumeter.create_line(0, y, 1, y, width=4, fill='green', dash=(9,1), dashoff=6+VM_OFFSET))
-                self.yellow.append(self.vumeter.create_line(self.B1, y, self.B1, y, width=4, fill='yellow', dash=(9,1), dashoff=9))
-                self.red.append(self.vumeter.create_line(self.B2, y, self.B2, y, width=4, fill='red', dash=(9,1), dashoff=0))
+                self.green.append(self.vumeter.create_line(0, y, 1, y, width=4,
+                                                           fill='green',
+                                                           dash=(9, 1),
+                                                           dashoff=6+VM_OFFSET))
+                self.yellow.append(self.vumeter.create_line(self.B1, y, self.B1,
+                                                            y, width=4,
+                                                            fill='yellow',
+                                                            dash=(9, 1),
+                                                            dashoff=9))
+                self.red.append(self.vumeter.create_line(self.B2, y, self.B2, y,
+                                                         width=4, fill='red',
+                                                         dash=(9, 1), dashoff=0))
             self.vumeter.grid(ipadx=5, row=row, column=0, columnspan=3)
             row += 1
 
         if self.timer:
-            self.timer_label = Label(self, text='Elapsed time (h:m:s:ms)')
+            self.timer_label = tk.Label(self, text='Elapsed time (h:m:s:ms)')
             self.timer_label.grid(ipadx=0, row=row, column=0, columnspan=3)
             row += 1
-            self.timer_strvar = StringVar(self, " 00 : 00 : 00 : 000")
-            self.timetext = Label(self, textvariable=self.timer_strvar)
+            self.timer_strvar = tk.StringVar(self, " 00 : 00 : 00 : 000")
+            self.timetext = tk.Label(self, textvariable=self.timer_strvar)
             self.timetext.grid(ipadx=5, row=row, column=0, columnspan=3)
             row += 1
 
         if self.locals is not None:
-            self.interp_label = Label(self, text='Interpreter')
+            self.interp_label = tk.Label(self, text='Interpreter')
             self.interp_label.grid(ipadx=0, row=row, column=0, columnspan=3)
             row += 1
-            self.text = Text(self, height=1, width=33, bd=1, relief=RIDGE, highlightthickness=0,
-                            spacing1=2, spacing3=2)
+            self.text = tk.Text(self, height=1, width=33, bd=1, relief=tk.RIDGE,
+                                highlightthickness=0, spacing1=2, spacing3=2)
             self.text.grid(ipadx=5, row=row, column=0, columnspan=3)
             self.text.bind("<Return>", self.getText)
             self.text.bind("<Up>", self.getPrev)
             self.text.bind("<Down>", self.getNext)
 
     def on_quit(self):
+        "Clean up on quit."
         self.shutdown()
         self.quit()
 
     def getPrev(self, event):
-        self.text.delete("1.0", END)
+        "Get previous command in history."
+        self.text.delete("1.0", tk.END)
         self._histo_count -= 1
         if self._histo_count < 0:
             self._histo_count = 0
@@ -322,10 +387,13 @@ class ServerGUI(Frame):
         return "break"
 
     def setTime(self, *args):
-        self.timer_strvar.set(" %02d : %02d : %02d : %03d" % (args[0], args[1], args[2], args[3]))
+        "Display the current server time."
+        txt = " %02d : %02d : %02d : %03d" % (args[0], args[1], args[2], args[3])
+        self.timer_strvar.set(txt)
 
     def getNext(self, event):
-        self.text.delete("1.0", END)
+        "Get next command in history."
+        self.text.delete("1.0", tk.END)
         self._histo_count += 1
         if self._histo_count >= len(self._history):
             self._histo_count = len(self._history)
@@ -334,28 +402,31 @@ class ServerGUI(Frame):
         return "break"
 
     def getText(self, event):
-        source = self.text.get("1.0", END)
-        self.text.delete("1.0", END)
+        "Retrieve text from the interpreter widget."
+        source = self.text.get("1.0", tk.END)
+        self.text.delete("1.0", tk.END)
         exec(source, self.locals)
         self._history.append(source)
         self._histo_count = len(self._history)
         return "break"
 
     def start(self, justSet=False):
-        if self._started == False:
+        "Start/stop the server."
+        if self._started is False:
             if not justSet:
                 self.startf()
             self._started = True
             self.startStringVar.set('Stop')
-            self.quitButton.configure(state = DISABLED)
+            self.quitButton.configure(state=tk.DISABLED)
         else:
             self.stopf()
             self._started = False
             self.startStringVar.set('Start')
-            self.quitButton.configure(state = NORMAL)
+            self.quitButton.configure(state=tk.NORMAL)
 
     def record(self):
-        if self._recstarted == False:
+        "Record sound on disk."
+        if self._recstarted is False:
             self.recstartf()
             self._recstarted = True
             self.recStringVar.set('Rec Stop')
@@ -365,9 +436,11 @@ class ServerGUI(Frame):
             self.recStringVar.set('Rec Start')
 
     def setAmp(self, value):
+        "Update server's global amplitude value."
         self.ampf(math.pow(10.0, float(value) * 0.05))
 
     def setRms(self, *args):
+        "Update the vumeter."
         for i in range(self.nchnls):
             y = 5 * (i + 1) + 1 - VM_OFFSET
             db = math.log10(args[i]+0.00001) * 0.2 + 1.
diff --git a/pyolib/_widgets.py b/pyolib/_widgets.py
index f4a32e6..a0b9dad 100644
--- a/pyolib/_widgets.py
+++ b/pyolib/_widgets.py
@@ -1,4 +1,9 @@
-# -*- coding: utf-8 -*-
+# encoding: utf-8
+"""
+This module is the interface between pyo's display demands and the different
+available GUI toolkits (wxpython of tkinter).
+
+"""
 from __future__ import print_function
 from __future__ import absolute_import
 """
@@ -20,7 +25,9 @@ GNU Lesser General Public License for more details.
 You should have received a copy of the GNU Lesser General Public
 License along with pyo.  If not, see <http://www.gnu.org/licenses/>.
 """
-import math, sys, os, random
+import sys
+import os
+import random
 
 use_wx = 1
 if "PYO_GUI_WX" in os.environ:
@@ -48,9 +55,9 @@ PYO_USE_TK = False
 if not PYO_USE_WX:
     try:
         if sys.version_info[0] < 3:
-            from Tkinter import *
+            import Tkinter as tk
         else:
-            from tkinter import *
+            import tkinter as tk
         from ._tkwidgets import *
         PYO_USE_TK = True
     except:
@@ -74,9 +81,10 @@ SCOPEWINDOWS = []
 EXPREDITORWINDOWS = []
 
 def createRootWindow():
+    "Creates the main window (app object)."
     if not PYO_USE_WX:
         if len(WINDOWS) == 0:
-            root = Tk()
+            root = tk.Tk()
             root.withdraw()
             return None
         else:
@@ -89,23 +97,29 @@ def createRootWindow():
             return None
 
 def tkCloseWindow(win):
+    "Closes a tkinter window."
     win.destroy()
-    if win in WINDOWS: WINDOWS.remove(win)
+    if win in WINDOWS:
+        WINDOWS.remove(win)
 
 def tkCloseWindowFromKeyboard(event):
+    "Closes a tkinter window from a keyboard event."
     win = event.widget
     if not isinstance(win, ServerGUI):
         win.destroy()
-        if win in WINDOWS: WINDOWS.remove(win)
+        if win in WINDOWS:
+            WINDOWS.remove(win)
 
 def tkCreateToplevelWindow():
-    win = Toplevel()
+    "Creates a tkinter top level window."
+    win = tk.Toplevel()
     WINDOWS.append(win)
     win.protocol('WM_DELETE_WINDOW', lambda win=win: tkCloseWindow(win))
     win.bind("<Escape>", tkCloseWindowFromKeyboard)
     return win
 
 def wxDisplayWindow(f, title):
+    "Displays a wxpython window on the screen."
     global CURRENT_X, MAX_X, NEXT_Y
     f.SetTitle(title)
     x, y = f.GetSize()
@@ -113,46 +127,55 @@ def wxDisplayWindow(f, title):
         y += 25
     if y + NEXT_Y < Y:
         px, py, NEXT_Y = CURRENT_X, NEXT_Y, NEXT_Y + y
-        if x + CURRENT_X > MAX_X: MAX_X = x + CURRENT_X
+        if x + CURRENT_X > MAX_X:
+            MAX_X = x + CURRENT_X
         f.SetPosition((px, py))
     elif x + MAX_X < X:
         px, py, NEXT_Y, CURRENT_X = MAX_X, 50, 50 + y, MAX_X
-        if x + CURRENT_X > MAX_X: MAX_X = x + CURRENT_X
+        if x + CURRENT_X > MAX_X:
+            MAX_X = x + CURRENT_X
         f.SetPosition((px, py))
     else:
-        f.SetPosition((random.randint(250,500), random.randint(200,400)))
+        f.SetPosition((random.randint(250, 500), random.randint(200, 400)))
     f.Show()
 
 def wxShowWindow(f, title, root):
+    "Shows a wxpython window on the screen."
     f.SetTitle(title)
     f.Show()
     if root is not None:
         root.MainLoop()
 
 def wxCreateDelayedCtrlWindows():
+    "Postponed a wxpython window display."
     for win in CTRLWINDOWS:
         f = PyoObjectControl(None, win[0], win[1])
-        if win[2] is None: title = win[0].__class__.__name__
+        if win[2] is None:
+            title = win[0].__class__.__name__
         else: title = win[2]
         wxDisplayWindow(f, title)
 
 def wxCreateDelayedGraphWindows():
+    "Postponed a wxpython window display."
     for win in GRAPHWINDOWS:
         f = TableGrapher(None, win[0], win[1], win[2], win[3])
-        if win[4] is None: title = win[0].__class__.__name__
+        if win[4] is None:
+            title = win[0].__class__.__name__
         else: title = win[4]
         wxDisplayWindow(f, title)
 
 def wxCreateDelayedDataGraphWindows():
+    "Postponed a wxpython window display."
     for win in DATAGRAPHWINDOWS:
         f = DataTableGrapher(None, win[0], win[1])
         win[0]._setGraphFrame(f)
-        if win[2] is None: title = win[0].__class__.__name__
+        if win[2] is None:
+            title = win[0].__class__.__name__
         else: title = win[2]
         wxDisplayWindow(f, title)
 
 def wxCreateDelayedTableWindows():
-    global CURRENT_X, MAX_X, NEXT_Y
+    "Postponed a wxpython window display."
     for win in TABLEWINDOWS:
         object = win[3]
         f = ViewTable(None, win[0], win[1], object)
@@ -161,14 +184,14 @@ def wxCreateDelayedTableWindows():
         wxDisplayWindow(f, win[2])
 
 def wxCreateDelayedSndTableWindows():
-    global CURRENT_X, MAX_X, NEXT_Y
+    "Postponed a wxpython window display."
     for win in SNDTABLEWINDOWS:
         f = SndViewTable(None, win[0], win[1], win[3])
         win[0]._setViewFrame(f)
         wxDisplayWindow(f, win[2])
 
 def wxCreateDelayedMatrixWindows():
-    global CURRENT_X, MAX_X, NEXT_Y
+    "Postponed a wxpython window display."
     for win in MATRIXWINDOWS:
         object = win[3]
         f = ViewMatrix(None, win[0], win[1], object)
@@ -177,73 +200,91 @@ def wxCreateDelayedMatrixWindows():
         wxDisplayWindow(f, win[2])
 
 def wxCreateDelayedSpectrumWindows():
+    "Postponed a wxpython window display."
     for win in SPECTRUMWINDOWS:
         f = SpectrumDisplay(None, win[0])
-        if win[1] is None: title = win[0].__class__.__name__
-        else: title = win[1]
+        if win[1] is None:
+            title = win[0].__class__.__name__
+        else:
+            title = win[1]
         if win[0] is not None:
             win[0]._setViewFrame(f)
         wxDisplayWindow(f, title)
 
 def wxCreateDelayedScopeWindows():
+    "Postponed a wxpython window display."
     for win in SCOPEWINDOWS:
         f = ScopeDisplay(None, win[0])
-        if win[1] is None: title = win[0].__class__.__name__
-        else: title = win[1]
+        if win[1] is None:
+            title = win[0].__class__.__name__
+        else:
+            title = win[1]
         if win[0] is not None:
             win[0]._setViewFrame(f)
         wxDisplayWindow(f, title)
 
 def wxCreateDelayedExprEditorWindows():
+    "Postponed a wxpython window display."
     for win in EXPREDITORWINDOWS:
         f = ExprEditorFrame(None, win[0])
-        if win[1] is None: title = win[0].__class__.__name__
-        else: title = win[1]
+        if win[1] is None:
+            title = win[0].__class__.__name__
+        else:
+            title = win[1]
         wxDisplayWindow(f, title)
 
 def createCtrlWindow(obj, map_list, title, wxnoserver=False):
+    "Creates a controller window (from a .ctrl() method."
     if not PYO_USE_WX:
         createRootWindow()
         win = tkCreateToplevelWindow()
         f = PyoObjectControl(win, obj, map_list)
         win.resizable(True, False)
-        if title is None: title = obj.__class__.__name__
+        if title is None:
+            title = obj.__class__.__name__
         win.title(title)
     else:
         if wxnoserver or wx.GetApp() is not None:
             root = createRootWindow()
             f = PyoObjectControl(None, obj, map_list)
-            if title is None: title = obj.__class__.__name__
+            if title is None:
+                title = obj.__class__.__name__
             wxShowWindow(f, title, root)
         else:
             CTRLWINDOWS.append([obj, map_list, title])
 
 def createGraphWindow(obj, mode, xlen, yrange, title, wxnoserver=False):
+    "Creates a grapher window (from a .graph() method."
     if not PYO_USE_WX:
         print("WxPython must be installed to use the 'graph()' method.")
     else:
         if wxnoserver or wx.GetApp() is not None:
             root = createRootWindow()
             f = TableGrapher(None, obj, mode, xlen, yrange)
-            if title is None: title = obj.__class__.__name__
+            if title is None:
+                title = obj.__class__.__name__
             wxShowWindow(f, title, root)
         else:
             GRAPHWINDOWS.append([obj, mode, xlen, yrange, title])
 
 def createDataGraphWindow(obj, yrange, title, wxnoserver=False):
+    "Creates a data table grapher window (from a .graph() method."
     if not PYO_USE_WX:
         print("WxPython must be installed to use the 'graph()' method.")
     else:
         if wxnoserver or wx.GetApp() is not None:
             root = createRootWindow()
             f = DataTableGrapher(None, obj, yrange)
-            if title is None: title = obj.__class__.__name__
+            if title is None:
+                title = obj.__class__.__name__
             obj._setGraphFrame(f)
             wxShowWindow(f, title, root)
         else:
             DATAGRAPHWINDOWS.append([obj, yrange, title])
 
-def createViewTableWindow(samples, title="Table waveform", wxnoserver=False, tableclass=None, object=None):
+def createViewTableWindow(samples, title="Table waveform", wxnoserver=False,
+                          tableclass=None, object=None):
+    "Creates a table view window (from a .view() method."
     if not PYO_USE_WX:
         createRootWindow()
         win = tkCreateToplevelWindow()
@@ -260,7 +301,9 @@ def createViewTableWindow(samples, title="Table waveform", wxnoserver=False, tab
         else:
             TABLEWINDOWS.append([samples, tableclass, title, object])
 
-def createSndViewTableWindow(obj, title="Table waveform", wxnoserver=False, tableclass=None, mouse_callback=None):
+def createSndViewTableWindow(obj, title="Table waveform", wxnoserver=False,
+                             tableclass=None, mouse_callback=None):
+    "Creates a snd table view window (from a .view() method."
     if not PYO_USE_WX:
         createRootWindow()
         win = tkCreateToplevelWindow()
@@ -271,13 +314,16 @@ def createSndViewTableWindow(obj, title="Table waveform", wxnoserver=False, tabl
         if wxnoserver or wx.GetApp() is not None:
             root = createRootWindow()
             f = SndViewTable(None, obj, tableclass, mouse_callback)
-            if title is None: title = obj.__class__.__name__
+            if title is None:
+                title = obj.__class__.__name__
             obj._setViewFrame(f)
             wxShowWindow(f, title, root)
         else:
             SNDTABLEWINDOWS.append([obj, tableclass, title, mouse_callback])
 
-def createViewMatrixWindow(samples, size, title="Matrix viewer", wxnoserver=False, object=None):
+def createViewMatrixWindow(samples, size, title="Matrix viewer",
+                           wxnoserver=False, object=None):
+    "Creates a matrix view window (from a .view() method."
     if not PYO_USE_WX:
         createRootWindow()
         win = tkCreateToplevelWindow()
@@ -292,16 +338,18 @@ def createViewMatrixWindow(samples, size, title="Matrix viewer", wxnoserver=Fals
                 object._setViewFrame(f)
             wxShowWindow(f, title, root)
         else:
-            MATRIXWINDOWS.append([samples,size,title, object])
+            MATRIXWINDOWS.append([samples, size, title, object])
 
 def createSpectrumWindow(object, title, wxnoserver=False):
+    "Creates a spectrum display."
     if not PYO_USE_WX:
         print("WxPython must be installed to use the Spectrum display.")
     else:
         if wxnoserver or wx.GetApp() is not None:
             root = createRootWindow()
             f = SpectrumDisplay(None, object)
-            if title is None: title = object.__class__.__name__
+            if title is None:
+                title = object.__class__.__name__
             if object is not None:
                 object._setViewFrame(f)
             wxShowWindow(f, title, root)
@@ -309,13 +357,15 @@ def createSpectrumWindow(object, title, wxnoserver=False):
             SPECTRUMWINDOWS.append([object, title])
 
 def createScopeWindow(object, title, wxnoserver=False):
+    "Creates a scope display."
     if not PYO_USE_WX:
         print("WxPython must be installed to use the Scope display.")
     else:
         if wxnoserver or wx.GetApp() is not None:
             root = createRootWindow()
             f = ScopeDisplay(None, object)
-            if title is None: title = object.__class__.__name__
+            if title is None:
+                title = object.__class__.__name__
             if object is not None:
                 object._setViewFrame(f)
             wxShowWindow(f, title, root)
@@ -323,32 +373,39 @@ def createScopeWindow(object, title, wxnoserver=False):
             SCOPEWINDOWS.append([object, title])
 
 def createExprEditorWindow(object, title, wxnoserver=False):
+    "Creates an expression editor window."
     if not PYO_USE_WX:
         print("WxPython must be installed to use the Expr editor display.")
     else:
         if wxnoserver or wx.GetApp() is not None:
             root = createRootWindow()
             f = ExprEditorFrame(None, object)
-            if title is None: title = object.__class__.__name__
+            if title is None:
+                title = object.__class__.__name__
             wxShowWindow(f, title, root)
         else:
             EXPREDITORWINDOWS.append([object, title])
 
-def createServerGUI(nchnls, start, stop, recstart, recstop, setAmp, started, locals, shutdown, meter, timer, amp, exit):
+def createServerGUI(nchnls, start, stop, recstart, recstop, setAmp, started,
+                    locals, shutdown, meter, timer, amp, exit):
+    "Creates the server's GUI."
     global X, Y, MAX_X, NEXT_Y
     if not PYO_USE_WX:
         createRootWindow()
         win = tkCreateToplevelWindow()
-        f = ServerGUI(win, nchnls, start, stop, recstart, recstop, setAmp, started, locals, shutdown, meter, timer, amp)
+        f = ServerGUI(win, nchnls, start, stop, recstart, recstop, setAmp,
+                      started, locals, shutdown, meter, timer, amp)
         f.master.title("pyo server")
         f.focus_set()
     else:
         win = createRootWindow()
-        f = ServerGUI(None, nchnls, start, stop, recstart, recstop, setAmp, started, locals, shutdown, meter, timer, amp, exit)
+        f = ServerGUI(None, nchnls, start, stop, recstart, recstop, setAmp,
+                      started, locals, shutdown, meter, timer, amp, exit)
         f.SetTitle("pyo server")
         f.SetPosition((30, 30))
         f.Show()
-        X,Y = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_X)-50, wx.SystemSettings.GetMetric(wx.SYS_SCREEN_Y)-50
+        X, Y = (wx.SystemSettings.GetMetric(wx.SYS_SCREEN_X) - 50,
+                wx.SystemSettings.GetMetric(wx.SYS_SCREEN_Y) - 50)
         if sys.platform.startswith("linux"):
             MAX_X, NEXT_Y = f.GetSize()[0]+30, f.GetSize()[1]+55
         else:
diff --git a/pyolib/_wxwidgets.py b/pyolib/_wxwidgets.py
index 4ea6228..68d55c8 100644
--- a/pyolib/_wxwidgets.py
+++ b/pyolib/_wxwidgets.py
@@ -53,9 +53,11 @@ def toExp(t, v1, v2):
 
 POWOFTWO = {2:1, 4:2, 8:3, 16:4, 32:5, 64:6, 128:7, 256:8, 512:9, 1024:10, 2048:11, 4096:12, 8192:13, 16384:14, 32768:15, 65536:16}
 def powOfTwo(x):
+    "Return 2 raised to the power of x."
     return 2**x
 
 def powOfTwoToInt(x):
+    "Return the exponent of 2 correponding to the value x."
     return POWOFTWO[x]
 
 def GetRoundBitmap( w, h, r ):
diff --git a/pyolib/analysis.py b/pyolib/analysis.py
index 38b8ce6..4189cbf 100644
--- a/pyolib/analysis.py
+++ b/pyolib/analysis.py
@@ -73,6 +73,7 @@ class Follower(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, freq, mul, add, lmax = convertArgsToLists(self._in_fader, freq, mul, add)
         self._base_objs = [Follower_base(wrap(in_fader,i), wrap(freq,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -168,6 +169,7 @@ class Follower2(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, risetime, falltime, mul, add, lmax = convertArgsToLists(self._in_fader, risetime, falltime, mul, add)
         self._base_objs = [Follower2_base(wrap(in_fader,i), wrap(risetime,i), wrap(falltime, i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -280,6 +282,7 @@ class ZCross(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, thresh, mul, add, lmax = convertArgsToLists(self._in_fader, thresh, mul, add)
         self._base_objs = [ZCross_base(wrap(in_fader,i), wrap(thresh,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -393,6 +396,7 @@ class Yin(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, tolerance, minfreq, maxfreq, cutoff, winsize, mul, add, lmax = convertArgsToLists(self._in_fader, tolerance, minfreq, maxfreq, cutoff, winsize, mul, add)
         self._base_objs = [Yin_base(wrap(in_fader,i), wrap(tolerance,i), wrap(minfreq,i), wrap(maxfreq,i), wrap(cutoff,i), wrap(winsize,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -559,6 +563,7 @@ class Centroid(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, size, mul, add, lmax = convertArgsToLists(self._in_fader, size, mul, add)
         self._base_objs = [Centroid_base(wrap(in_fader,i), wrap(size,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -644,6 +649,7 @@ class AttackDetector(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, deltime, cutoff, maxthresh, minthresh, reltime, mul, add, lmax = convertArgsToLists(self._in_fader, deltime, cutoff, maxthresh, minthresh, reltime, mul, add)
         self._base_objs = [AttackDetector_base(wrap(in_fader,i), wrap(deltime,i), wrap(cutoff,i), wrap(maxthresh,i), wrap(minthresh,i), wrap(reltime,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -866,6 +872,7 @@ class Spectrum(PyoObject):
         self._timer = Pattern(self.refreshView, 0.05).play()
         if function is None:
             self.view()
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -1305,6 +1312,7 @@ class Scope(PyoObject):
         self._timer = Pattern(self.refreshView, length).play()
         if function is None:
             self.view()
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -1525,6 +1533,7 @@ class PeakAmp(PyoObject):
         sr = self.getSamplingRate()
         bs = self.getBufferSize()
         self._timer = Pattern(self._buildList, 0.06).play()
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
diff --git a/pyolib/arithmetic.py b/pyolib/arithmetic.py
index e8d300e..f38e056 100644
--- a/pyolib/arithmetic.py
+++ b/pyolib/arithmetic.py
@@ -54,6 +54,7 @@ class Sin(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, mul, add, lmax = convertArgsToLists(self._in_fader, mul, add)
         self._base_objs = [M_Sin_base(wrap(in_fader,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -105,6 +106,7 @@ class Cos(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, mul, add, lmax = convertArgsToLists(self._in_fader, mul, add)
         self._base_objs = [M_Cos_base(wrap(in_fader,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -163,6 +165,7 @@ class Tan(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, mul, add, lmax = convertArgsToLists(self._in_fader, mul, add)
         self._base_objs = [M_Tan_base(wrap(in_fader,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -216,6 +219,7 @@ class Abs(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, mul, add, lmax = convertArgsToLists(self._in_fader, mul, add)
         self._base_objs = [M_Abs_base(wrap(in_fader,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -274,6 +278,7 @@ class Sqrt(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, mul, add, lmax = convertArgsToLists(self._in_fader, mul, add)
         self._base_objs = [M_Sqrt_base(wrap(in_fader,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -328,6 +333,7 @@ class Log(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, mul, add, lmax = convertArgsToLists(self._in_fader, mul, add)
         self._base_objs = [M_Log_base(wrap(in_fader,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -382,6 +388,7 @@ class Log2(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, mul, add, lmax = convertArgsToLists(self._in_fader, mul, add)
         self._base_objs = [M_Log2_base(wrap(in_fader,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -436,6 +443,7 @@ class Log10(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, mul, add, lmax = convertArgsToLists(self._in_fader, mul, add)
         self._base_objs = [M_Log10_base(wrap(in_fader,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -493,6 +501,7 @@ class Atan2(PyoObject):
         self._a = a
         b, a, mul, add, lmax = convertArgsToLists(b, a, mul, add)
         self._base_objs = [M_Atan2_base(wrap(b,i), wrap(a,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setB(self, x):
         """
@@ -568,6 +577,7 @@ class Floor(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, mul, add, lmax = convertArgsToLists(self._in_fader, mul, add)
         self._base_objs = [M_Floor_base(wrap(in_fader,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -622,6 +632,7 @@ class Ceil(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, mul, add, lmax = convertArgsToLists(self._in_fader, mul, add)
         self._base_objs = [M_Ceil_base(wrap(in_fader,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -676,6 +687,7 @@ class Round(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, mul, add, lmax = convertArgsToLists(self._in_fader, mul, add)
         self._base_objs = [M_Round_base(wrap(in_fader,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -728,6 +740,7 @@ class Tanh(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, mul, add, lmax = convertArgsToLists(self._in_fader, mul, add)
         self._base_objs = [M_Tanh_base(wrap(in_fader,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -784,6 +797,7 @@ class Exp(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, mul, add, lmax = convertArgsToLists(self._in_fader, mul, add)
         self._base_objs = [M_Exp_base(wrap(in_fader,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
diff --git a/pyolib/controls.py b/pyolib/controls.py
index 00b21bf..f1db3d9 100644
--- a/pyolib/controls.py
+++ b/pyolib/controls.py
@@ -814,6 +814,7 @@ class SigTo(PyoObject):
         self._time = time
         value, time, init, mul ,add, lmax = convertArgsToLists(value, time, init, mul, add)
         self._base_objs = [SigTo_base(wrap(value,i), wrap(time,i), wrap(init,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setValue(self, x):
         """
diff --git a/pyolib/dynamics.py b/pyolib/dynamics.py
index 872f0d2..1b45e52 100644
--- a/pyolib/dynamics.py
+++ b/pyolib/dynamics.py
@@ -59,6 +59,7 @@ class Clip(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, min, max, mul, add, lmax = convertArgsToLists(self._in_fader, min, max, mul, add)
         self._base_objs = [Clip_base(wrap(in_fader,i), wrap(min,i), wrap(max,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -173,6 +174,7 @@ class Mirror(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, min, max, mul, add, lmax = convertArgsToLists(self._in_fader, min, max, mul, add)
         self._base_objs = [Mirror_base(wrap(in_fader,i), wrap(min,i), wrap(max,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -285,6 +287,7 @@ class Degrade(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, bitdepth, srscale, mul, add, lmax = convertArgsToLists(self._in_fader, bitdepth, srscale, mul, add)
         self._base_objs = [Degrade_base(wrap(in_fader,i), wrap(bitdepth,i), wrap(srscale,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -421,6 +424,7 @@ class Compress(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, thresh, ratio, risetime, falltime, lookahead, knee, outputAmp, mul, add, lmax = convertArgsToLists(self._in_fader, thresh, ratio, risetime, falltime, lookahead, knee, outputAmp, mul, add)
         self._base_objs = [Compress_base(wrap(in_fader,i), wrap(thresh,i), wrap(ratio,i), wrap(risetime,i), wrap(falltime,i), wrap(lookahead,i), wrap(knee,i), wrap(outputAmp,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -639,6 +643,7 @@ class Gate(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, thresh, risetime, falltime, lookahead, outputAmp, mul, add, lmax = convertArgsToLists(self._in_fader, thresh, risetime, falltime, lookahead, outputAmp, mul, add)
         self._base_objs = [Gate_base(wrap(in_fader,i), wrap(thresh,i), wrap(risetime,i), wrap(falltime,i), wrap(lookahead,i), wrap(outputAmp,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -793,6 +798,7 @@ class Balance(PyoObject):
         self._in_fader2 = InputFader(input2)
         in_fader, in_fader2, freq, mul, add, lmax = convertArgsToLists(self._in_fader, self._in_fader2, freq, mul, add)
         self._base_objs = [Balance_base(wrap(in_fader,i), wrap(in_fader2,i), wrap(freq,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -902,6 +908,7 @@ class Min(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, comp, mul, add, lmax = convertArgsToLists(self._in_fader, comp, mul, add)
         self._base_objs = [Min_base(wrap(in_fader,i), wrap(comp,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -982,6 +989,7 @@ class Max(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, comp, mul, add, lmax = convertArgsToLists(self._in_fader, comp, mul, add)
         self._base_objs = [Max_base(wrap(in_fader,i), wrap(comp,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
diff --git a/pyolib/effects.py b/pyolib/effects.py
index a445139..221025b 100644
--- a/pyolib/effects.py
+++ b/pyolib/effects.py
@@ -79,6 +79,7 @@ class Disto(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, drive, slope, mul, add, lmax = convertArgsToLists(self._in_fader, drive, slope, mul, add)
         self._base_objs = [Disto_base(wrap(in_fader,i), wrap(drive,i), wrap(slope,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -199,6 +200,7 @@ class Delay(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, delay, feedback, maxdelay, mul, add, lmax = convertArgsToLists(self._in_fader, delay, feedback, maxdelay, mul, add)
         self._base_objs = [Delay_base(wrap(in_fader,i), wrap(delay,i), wrap(feedback,i), wrap(maxdelay,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -317,6 +319,7 @@ class SDelay(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, delay, maxdelay, mul, add, lmax = convertArgsToLists(self._in_fader, delay, maxdelay, mul, add)
         self._base_objs = [SDelay_base(wrap(in_fader,i), wrap(delay,i), wrap(maxdelay,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -414,6 +417,7 @@ class Waveguide(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, freq, dur, minfreq, mul, add, lmax = convertArgsToLists(self._in_fader, freq, dur, minfreq, mul, add)
         self._base_objs = [Waveguide_base(wrap(in_fader,i), wrap(freq,i), wrap(dur,i), wrap(minfreq,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -540,6 +544,7 @@ class AllpassWG(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, freq, feed, detune, minfreq, mul, add, lmax = convertArgsToLists(self._in_fader, freq, feed, detune, minfreq, mul, add)
         self._base_objs = [AllpassWG_base(wrap(in_fader,i), wrap(freq,i), wrap(feed,i), wrap(detune,i), wrap(minfreq,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -686,6 +691,7 @@ class Freeverb(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, size, damp, bal, mul, add, lmax = convertArgsToLists(self._in_fader, size, damp, bal, mul, add)
         self._base_objs = [Freeverb_base(wrap(in_fader,i), wrap(size,i), wrap(damp,i), wrap(bal,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -842,6 +848,7 @@ class Convolve(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, table, size, mul, add, lmax = convertArgsToLists(self._in_fader, table, size, mul, add)
         self._base_objs = [Convolve_base(wrap(in_fader,i), wrap(table,i), wrap(size,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -931,6 +938,7 @@ class WGVerb(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, feedback, cutoff, bal, mul, add, lmax = convertArgsToLists(self._in_fader, feedback, cutoff, bal, mul, add)
         self._base_objs = [WGVerb_base(wrap(in_fader,i), wrap(feedback,i), wrap(cutoff,i), wrap(bal,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -1073,6 +1081,7 @@ class Chorus(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, depth, feedback, bal, mul, add, lmax = convertArgsToLists(self._in_fader, depth, feedback, bal, mul, add)
         self._base_objs = [Chorus_base(wrap(in_fader,i), wrap(depth,i), wrap(feedback,i), wrap(bal,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -1212,6 +1221,7 @@ class Harmonizer(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, transpo, feedback, winsize, mul, add, lmax = convertArgsToLists(self._in_fader, transpo, feedback, winsize, mul, add)
         self._base_objs = [Harmonizer_base(wrap(in_fader,i), wrap(transpo,i), wrap(feedback,i), wrap(winsize,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -1345,6 +1355,7 @@ class Delay1(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, mul, add, lmax = convertArgsToLists(self._in_fader, mul, add)
         self._base_objs = [Delay1_base(wrap(in_fader,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -1428,6 +1439,7 @@ class STRev(PyoObject):
         in_fader, inpos, revtime, cutoff, bal, roomSize, firstRefGain, mul, add, lmax = convertArgsToLists(self._in_fader, inpos, revtime, cutoff, bal, roomSize, firstRefGain, mul, add)
         self._base_players = [STReverb_base(wrap(in_fader,i), wrap(inpos,i), wrap(revtime,i), wrap(cutoff,i), wrap(bal,i), wrap(roomSize,i), wrap(firstRefGain,i)) for i in range(lmax)]
         self._base_objs = [STRev_base(wrap(self._base_players,i), j, wrap(mul,i), wrap(add,i)) for i in range(lmax) for j in range(2)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -1655,6 +1667,7 @@ class SmoothDelay(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, delay, feedback, crossfade, maxdelay, mul, add, lmax = convertArgsToLists(self._in_fader, delay, feedback, crossfade, maxdelay, mul, add)
         self._base_objs = [SmoothDelay_base(wrap(in_fader,i), wrap(delay,i), wrap(feedback,i), wrap(crossfade,i), wrap(maxdelay,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -1807,6 +1820,7 @@ class FreqShift(PyoObject):
             self._mod_objs.append(Mix(self._hilb_objs[-1]['real'] * self._sin_objs[-1] + self._hilb_objs[-1]['imag'] * self._cos_objs[-1],
                                       mul=wrap(mul,i), add=wrap(add,i)))
             self._base_objs.extend(self._mod_objs[-1].getBaseObjects())
+        self.play()
 
     def play(self, dur=0, delay=0):
         dur, delay, lmax = convertArgsToLists(dur, delay)
diff --git a/pyolib/expression.py b/pyolib/expression.py
index e4cb58d..41f27ff 100644
--- a/pyolib/expression.py
+++ b/pyolib/expression.py
@@ -306,6 +306,7 @@ class Expr(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, expr, mul, add, lmax = convertArgsToLists(self._in_fader, expr, mul, add)
         self._base_objs = [Expr_base(wrap(in_fader,i), to_unicode(wrap(expr,i)), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
diff --git a/pyolib/filters.py b/pyolib/filters.py
index a280683..852f5af 100644
--- a/pyolib/filters.py
+++ b/pyolib/filters.py
@@ -80,6 +80,7 @@ class Biquad(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, freq, q, type, mul, add, lmax = convertArgsToLists(self._in_fader, freq, q, type, mul, add)
         self._base_objs = [Biquad_base(wrap(in_fader,i), wrap(freq,i), wrap(q,i), wrap(type,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -229,6 +230,7 @@ class Biquadx(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, freq, q, type, stages, mul, add, lmax = convertArgsToLists(self._in_fader, freq, q, type, stages, mul, add)
         self._base_objs = [Biquadx_base(wrap(in_fader,i), wrap(freq,i), wrap(q,i), wrap(type,i), wrap(stages,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -408,6 +410,7 @@ class Biquada(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, b0, b1, b2, a0, a1, a2, mul, add, lmax = convertArgsToLists(self._in_fader, self._b0, self._b1, self._b2, self._a0, self._a1, self._a2, mul, add)
         self._base_objs = [Biquada_base(wrap(in_fader,i), wrap(b0,i), wrap(b1,i), wrap(b2,i), wrap(a0,i), wrap(a1,i), wrap(a2,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -632,6 +635,7 @@ class EQ(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, freq, q, boost, type, mul, add, lmax = convertArgsToLists(self._in_fader, freq, q, boost, type, mul, add)
         self._base_objs = [EQ_base(wrap(in_fader,i), wrap(freq,i), wrap(q,i), wrap(boost,i), wrap(type,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -782,6 +786,7 @@ class Tone(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, freq, mul, add, lmax = convertArgsToLists(self._in_fader, freq, mul, add)
         self._base_objs = [Tone_base(wrap(in_fader,i), wrap(freq,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -860,6 +865,7 @@ class Atone(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, freq, mul, add, lmax = convertArgsToLists(self._in_fader, freq, mul, add)
         self._base_objs = [Atone_base(wrap(in_fader,i), wrap(freq,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -951,6 +957,7 @@ class Port(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, risetime, falltime, init, mul, add, lmax = convertArgsToLists(self._in_fader, risetime, falltime, init, mul, add)
         self._base_objs = [Port_base(wrap(in_fader,i), wrap(risetime,i), wrap(falltime,i), wrap(init,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -1049,6 +1056,7 @@ class DCBlock(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, mul, add, lmax = convertArgsToLists(self._in_fader, mul, add)
         self._base_objs = [DCBlock_base(wrap(in_fader,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -1125,6 +1133,7 @@ class BandSplit(PyoObject):
         for j in range(num):
             for i in range(lmax):
                 self._base_objs.append(BandSplit_base(wrap(self._base_players,i), j, wrap(mul,j), wrap(add,j)))
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -1226,6 +1235,7 @@ class FourBand(PyoObject):
         for j in range(4):
             for i in range(lmax):
                 self._base_objs.append(FourBand_base(wrap(self._base_players,i), j, wrap(mul,j), wrap(add,j)))
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -1382,6 +1392,7 @@ class Hilbert(PyoObject):
             for j in range(lmax):
                 self._base_objs.append(Hilbert_base(wrap(self._base_players,j), 0, wrap(mul,i), wrap(add,i)))
                 self._base_objs.append(Hilbert_base(wrap(self._base_players,j), 1, wrap(mul,i), wrap(add,i)))
+        self.play()
 
     def __getitem__(self, str):
         if str == 'real':
@@ -1487,6 +1498,7 @@ class Allpass(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, delay, feedback, maxdelay, mul, add, lmax = convertArgsToLists(self._in_fader, delay, feedback, maxdelay, mul, add)
         self._base_objs = [Allpass_base(wrap(in_fader,i), wrap(delay,i), wrap(feedback,i), wrap(maxdelay,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -1601,6 +1613,7 @@ class Allpass2(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, freq, bw, mul, add, lmax = convertArgsToLists(self._in_fader, freq, bw, mul, add)
         self._base_objs = [Allpass2_base(wrap(in_fader,i), wrap(freq,i), wrap(bw,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -1722,6 +1735,7 @@ class Phaser(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, freq, spread, q, feedback, num, mul, add, lmax = convertArgsToLists(self._in_fader, freq, spread, q, feedback, num, mul, add)
         self._base_objs = [Phaser_base(wrap(in_fader,i), wrap(freq,i), wrap(spread,i), wrap(q,i), wrap(feedback,i), wrap(num,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -1909,6 +1923,7 @@ class Vocoder(PyoObject):
         self._in_fader2 = InputFader(input2)
         in_fader, in_fader2, freq, spread, q, slope, stages, mul, add, lmax = convertArgsToLists(self._in_fader, self._in_fader2, freq, spread, q, slope, stages, mul, add)
         self._base_objs = [Vocoder_base(wrap(in_fader,i), wrap(in_fader2,i), wrap(freq,i), wrap(spread,i), wrap(q,i), wrap(slope,i), wrap(stages,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -2139,6 +2154,7 @@ class IRWinSinc(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, freq, bw, type, order, mul, add, lmax = convertArgsToLists(self._in_fader, freq, bw, type, order, mul, add)
         self._base_objs = [IRWinSinc_base(wrap(in_fader,i), wrap(freq,i), wrap(bw,i), wrap(type,i), wrap(order,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -2287,6 +2303,7 @@ class IRAverage(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, order, mul, add, lmax = convertArgsToLists(self._in_fader, order, mul, add)
         self._base_objs = [IRAverage_base(wrap(in_fader,i), wrap(order,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -2374,6 +2391,7 @@ class IRPulse(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, freq, bw, type, order, mul, add, lmax = convertArgsToLists(self._in_fader, freq, bw, type, order, mul, add)
         self._base_objs = [IRPulse_base(wrap(in_fader,i), wrap(freq,i), wrap(bw,i), wrap(type,i), wrap(order,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -2533,6 +2551,7 @@ class IRFM(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, carrier, ratio, index, order, mul, add, lmax = convertArgsToLists(self._in_fader, carrier, ratio, index, order, mul, add)
         self._base_objs = [IRFM_base(wrap(in_fader,i), wrap(carrier,i), wrap(ratio,i), wrap(index,i), wrap(order,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -2674,6 +2693,7 @@ class SVF(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, freq, q, type, mul, add, lmax = convertArgsToLists(self._in_fader, freq, q, type, mul, add)
         self._base_objs = [SVF_base(wrap(in_fader,i), wrap(freq,i), wrap(q,i), wrap(type,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -2809,6 +2829,7 @@ class Average(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, size, mul, add, lmax = convertArgsToLists(self._in_fader, size, mul, add)
         self._base_objs = [Average_base(wrap(in_fader,i), wrap(size,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -2898,6 +2919,7 @@ class Reson(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, freq, q, mul, add, lmax = convertArgsToLists(self._in_fader, freq, q, mul, add)
         self._base_objs = [Reson_base(wrap(in_fader,i), wrap(freq,i), wrap(q,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -3014,6 +3036,7 @@ class Resonx(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, freq, q, stages, mul, add, lmax = convertArgsToLists(self._in_fader, freq, q, stages, mul, add)
         self._base_objs = [Resonx_base(wrap(in_fader,i), wrap(freq,i), wrap(q,i), wrap(stages,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -3140,6 +3163,7 @@ class ButLP(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, freq, mul, add, lmax = convertArgsToLists(self._in_fader, freq, mul, add)
         self._base_objs = [ButLP_base(wrap(in_fader,i), wrap(freq,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -3222,6 +3246,7 @@ class ButHP(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, freq, mul, add, lmax = convertArgsToLists(self._in_fader, freq, mul, add)
         self._base_objs = [ButHP_base(wrap(in_fader,i), wrap(freq,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -3308,6 +3333,7 @@ class ButBP(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, freq, q, mul, add, lmax = convertArgsToLists(self._in_fader, freq, q, mul, add)
         self._base_objs = [ButBP_base(wrap(in_fader,i), wrap(freq,i), wrap(q,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -3417,6 +3443,7 @@ class ButBR(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, freq, q, mul, add, lmax = convertArgsToLists(self._in_fader, freq, q, mul, add)
         self._base_objs = [ButBR_base(wrap(in_fader,i), wrap(freq,i), wrap(q,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -3526,6 +3553,7 @@ class MoogLP(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, freq, res, mul, add, lmax = convertArgsToLists(self._in_fader, freq, res, mul, add)
         self._base_objs = [MoogLP_base(wrap(in_fader,i), wrap(freq,i), wrap(res,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -3637,6 +3665,7 @@ class ComplexRes(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, freq, decay, mul, add, lmax = convertArgsToLists(self._in_fader, freq, decay, mul, add)
         self._base_objs = [ComplexRes_base(wrap(in_fader,i), wrap(freq,i), wrap(decay,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
diff --git a/pyolib/fourier.py b/pyolib/fourier.py
index ae8c0a7..ede6a75 100644
--- a/pyolib/fourier.py
+++ b/pyolib/fourier.py
@@ -124,6 +124,7 @@ class FFT(PyoObject):
             self._real_objs.append(FFT_base(wrap(self._base_players,j), 0, self._mul, self._add))
             self._imag_objs.append(FFT_base(wrap(self._base_players,j), 1, self._mul, self._add))
             self._bin_objs.append(FFT_base(wrap(self._base_players,j), 2, self._mul, self._add))
+        self.play()
 
     def __len__(self):
         return len(self._real_objs)
@@ -335,6 +336,7 @@ class IFFT(PyoObject):
         for i in range(lmax):
             hopsize = wrap(size,i) * ((i // ratio) % overlaps) // overlaps
             self._base_objs.append(IFFT_base(wrap(in_fader,i), wrap(in_fader2,i), wrap(size,i), hopsize, wrap(wintype,i), wrap(mul,i), wrap(add,i)))
+        self.play()
 
     def __len__(self):
         return len(self._inreal)
@@ -498,6 +500,7 @@ class CarToPol(PyoObject):
         for i in range(lmax):
             self._base_objs.append(CarToPol_base(wrap(in_fader,i), wrap(in_fader2,i), 0, wrap(mul,i), wrap(add,i)))
             self._base_objs.append(CarToPol_base(wrap(in_fader,i), wrap(in_fader2,i), 1, wrap(mul,i), wrap(add,i)))
+        self.play()
 
     def __len__(self):
         return len(self._inreal)
@@ -644,6 +647,7 @@ class PolToCar(PyoObject):
         for i in range(lmax):
             self._base_objs.append(PolToCar_base(wrap(in_fader,i), wrap(in_fader2,i), 0, wrap(mul,i), wrap(add,i)))
             self._base_objs.append(PolToCar_base(wrap(in_fader,i), wrap(in_fader2,i), 1, wrap(mul,i), wrap(add,i)))
+        self.play()
 
     def __len__(self):
         return len(self._inmag)
@@ -802,6 +806,7 @@ class FrameDelta(PyoObject):
             base_player = i % num_of_mains
             overlap = i // num_of_mains
             self._base_objs.append(FrameDelta_base(self._base_players[base_player], overlap, wrap(mul,i), wrap(add,i)))
+        self.play()
 
     def out(self, chnl=0, inc=1, dur=0, delay=0):
         return self.play(dur, delay)
@@ -925,6 +930,7 @@ class FrameAccum(PyoObject):
             base_player = i % num_of_mains
             overlap = i // num_of_mains
             self._base_objs.append(FrameAccum_base(self._base_players[base_player], overlap, wrap(mul,i), wrap(add,i)))
+        self.play()
 
     def out(self, chnl=0, inc=1, dur=0, delay=0):
         return self.play(dur, delay)
@@ -1046,6 +1052,7 @@ class Vectral(PyoObject):
             base_player = i % num_of_mains
             overlap = i // num_of_mains
             self._base_objs.append(Vectral_base(self._base_players[base_player], overlap, wrap(mul,i), wrap(add,i)))
+        self.play()
 
     def out(self, chnl=0, inc=1, dur=0, delay=0):
         return self.play(dur, delay)
@@ -1218,6 +1225,7 @@ class CvlVerb(PyoObject):
             _size, _dur, _snd_sr, _snd_chnls, _format, _type = sndinfo(file)
             lmax3 = max(lmax, _snd_chnls)
             self._base_objs.extend([CvlVerb_base(wrap(in_fader,i), file, wrap(bal,i), wrap(size,i), i%_snd_chnls, wrap(mul,i), wrap(add,i)) for i in range(lmax3)])
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
diff --git a/pyolib/generators.py b/pyolib/generators.py
index 22464ac..1df8932 100644
--- a/pyolib/generators.py
+++ b/pyolib/generators.py
@@ -62,6 +62,7 @@ class Sine(PyoObject):
         self._phase = phase
         freq, phase, mul, add, lmax = convertArgsToLists(freq, phase, mul, add)
         self._base_objs = [Sine_base(wrap(freq,i), wrap(phase,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setFreq(self, x):
         """
@@ -161,6 +162,7 @@ class FastSine(PyoObject):
         self._quality = quality
         freq, initphase, quality, mul, add, lmax = convertArgsToLists(freq, initphase, quality, mul, add)
         self._base_objs = [FastSine_base(wrap(freq,i), wrap(initphase,i), wrap(quality,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setFreq(self, x):
         """
@@ -253,6 +255,7 @@ class SineLoop(PyoObject):
         self._feedback = feedback
         freq, feedback, mul, add, lmax = convertArgsToLists(freq, feedback, mul, add)
         self._base_objs = [SineLoop_base(wrap(freq,i), wrap(feedback,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setFreq(self, x):
         """
@@ -335,6 +338,7 @@ class Phasor(PyoObject):
         self._phase = phase
         freq, phase, mul, add, lmax = convertArgsToLists(freq, phase, mul, add)
         self._base_objs = [Phasor_base(wrap(freq,i), wrap(phase,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setFreq(self, x):
         """
@@ -418,6 +422,7 @@ class Input(PyoObject):
         self._chnl = chnl
         chnl, mul, add, lmax = convertArgsToLists(chnl, mul, add)
         self._base_objs = [Input_base(wrap(chnl,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
         self._map_list = [SLMapMul(self._mul)]
@@ -440,6 +445,7 @@ class Noise(PyoObject):
         self._type = 0
         mul, add, lmax = convertArgsToLists(mul, add)
         self._base_objs = [Noise_base(wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setType(self, x):
         """
@@ -490,6 +496,7 @@ class PinkNoise(PyoObject):
         PyoObject.__init__(self, mul, add)
         mul, add, lmax = convertArgsToLists(mul, add)
         self._base_objs = [PinkNoise_base(wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
         self._map_list = [SLMapMul(self._mul)]
@@ -514,6 +521,7 @@ class BrownNoise(PyoObject):
         PyoObject.__init__(self, mul, add)
         mul, add, lmax = convertArgsToLists(mul, add)
         self._base_objs = [BrownNoise_base(wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
         self._map_list = [SLMapMul(self._mul)]
@@ -554,6 +562,7 @@ class FM(PyoObject):
         self._index = index
         carrier, ratio, index, mul, add, lmax = convertArgsToLists(carrier, ratio, index, mul, add)
         self._base_objs = [Fm_base(wrap(carrier,i), wrap(ratio,i), wrap(index,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setCarrier(self, x):
         """
@@ -672,6 +681,7 @@ class CrossFM(PyoObject):
         self._ind2 = ind2
         carrier, ratio, ind1, ind2, mul, add, lmax = convertArgsToLists(carrier, ratio, ind1, ind2, mul, add)
         self._base_objs = [CrossFm_base(wrap(carrier,i), wrap(ratio,i), wrap(ind1,i), wrap(ind2,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setCarrier(self, x):
         """
@@ -799,6 +809,7 @@ class Blit(PyoObject):
         self._harms = harms
         freq, harms, mul, add, lmax = convertArgsToLists(freq, harms, mul, add)
         self._base_objs = [Blit_base(wrap(freq,i), wrap(harms,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setFreq(self, x):
         """
@@ -901,6 +912,7 @@ class Rossler(PyoObject):
             self._base_objs.append(Rossler_base(wrap(pitch,i), wrap(chaos,i), wrap(mul,i), wrap(add,i)))
             if self._stereo:
                 self._base_objs.append(RosslerAlt_base(self._base_objs[-1], wrap(mul,i), wrap(add,i)))
+        self.play()
 
     def setPitch(self, x):
         """
@@ -1008,6 +1020,7 @@ class Lorenz(PyoObject):
             self._base_objs.append(Lorenz_base(wrap(pitch,i), wrap(chaos,i), wrap(mul,i), wrap(add,i)))
             if self._stereo:
                 self._base_objs.append(LorenzAlt_base(self._base_objs[-1], wrap(mul,i), wrap(add,i)))
+        self.play()
 
     def setPitch(self, x):
         """
@@ -1115,6 +1128,7 @@ class ChenLee(PyoObject):
             self._base_objs.append(ChenLee_base(wrap(pitch,i), wrap(chaos,i), wrap(mul,i), wrap(add,i)))
             if self._stereo:
                 self._base_objs.append(ChenLeeAlt_base(self._base_objs[-1], wrap(mul,i), wrap(add,i)))
+        self.play()
 
     def setPitch(self, x):
         """
@@ -1212,6 +1226,7 @@ class LFO(PyoObject):
         self._type = type
         freq, sharp, type, mul, add, lmax = convertArgsToLists(freq, sharp, type, mul, add)
         self._base_objs = [LFO_base(wrap(freq,i), wrap(sharp,i), wrap(type,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setFreq(self, x):
         """
@@ -1352,6 +1367,7 @@ class SumOsc(PyoObject):
         self._index = index
         freq, ratio, index, mul, add, lmax = convertArgsToLists(freq, ratio, index, mul, add)
         self._base_objs = [SumOsc_base(wrap(freq,i), wrap(ratio,i), wrap(index,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setFreq(self, x):
         """
@@ -1469,6 +1485,7 @@ class SuperSaw(PyoObject):
         self._bal = bal
         freq, detune, bal, mul, add, lmax = convertArgsToLists(freq, detune, bal, mul, add)
         self._base_objs = [SuperSaw_base(wrap(freq,i), wrap(detune,i), wrap(bal,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setFreq(self, x):
         """
@@ -1577,6 +1594,7 @@ class RCOsc(PyoObject):
         self._sharp = sharp
         freq, sharp, mul, add, lmax = convertArgsToLists(freq, sharp, mul, add)
         self._base_objs = [RCOsc_base(wrap(freq,i), wrap(sharp,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setFreq(self, x):
         """
diff --git a/pyolib/listener.py b/pyolib/listener.py
index b16b732..3fe6d32 100644
--- a/pyolib/listener.py
+++ b/pyolib/listener.py
@@ -25,11 +25,20 @@ class MidiListener(threading.Thread):
 
             def myfunc(status, data1, data2)
 
-        mididev: int, optional
+        mididev: int or list of ints, optional
             Sets the midi input device (see `pm_list_devices()` for the
             available devices). The default, -1, means the system default
             device. A number greater than the highest portmidi device index
-            will open all available input devices.
+            will open all available input devices. Specific devices can be
+            set with a list of integers.
+
+        reportdevice: boolean, optional
+            If True, the device ID will be reported as a fourth argument to
+            the callback. The signature will then be:
+
+            def myfunc(status, data1, data2, id)
+
+            Available at initialization only. Defaults to False.
 
     .. note::
 
@@ -44,12 +53,15 @@ class MidiListener(threading.Thread):
     >>> listen.start()
 
     """
-    def __init__(self, function, mididev=-1):
+    def __init__(self, function, mididev=-1, reportdevice=False):
         threading.Thread.__init__(self)
         self.daemon = True
         self._function = WeakMethod(function)
         self._mididev = mididev
-        self._listener = MidiListener_base(self._function, self._mididev)
+        if type(mididev) is not list:
+            mididev = [mididev]
+        self._reportdevice = reportdevice
+        self._listener = MidiListener_base(self._function, mididev, self._reportdevice)
 
     def run(self):
         """
@@ -63,6 +75,140 @@ class MidiListener(threading.Thread):
             except:
                 pass
 
+    def getDeviceInfos(self):
+        """
+        Returns infos about connected midi devices.
+
+        This method returns a list of dictionaries, one per device.
+
+        Dictionary format is:
+
+        {"id": device_id (int), "name": device_name (str), "interface": interface (str)}
+
+        """
+        infos = self._listener.getDeviceInfos()
+        if infos:
+            lst = []
+            for info in infos:
+                dct = {}
+                items = info.split(", ")
+                for item in items:
+                    isplit = item.split(": ")
+                    dct[isplit[0]] = isplit[1]
+                dct["id"] = int(dct["id"])
+                lst.append(dct)
+            return lst
+        return []
+
+class MidiDispatcher(threading.Thread):
+    """
+    Self-contained midi dispatcher thread.
+
+    This object allows to setup a Midi server that is independent
+    of the audio server (mainly to be able to send Midi data even
+    when the audio server is stopped). Although it runs in a separated
+    thread, the same device can't be used by this object and the audio
+    server at the same time. It is adviced to call the deactivateMidi()
+    method on the audio server to avoid conflicts.
+
+    Use the `send` method to send midi event to connected devices.
+
+    :Parent: threading.Thread
+
+    :Args:
+
+        mididev: int or list of ints, optional
+            Sets the midi output device (see `pm_list_devices()` for the
+            available devices). The default, -1, means the system default
+            device. A number greater than the highest portmidi device index
+            will open all available input devices. Specific devices can be
+            set with a list of integers.
+
+    .. note::
+
+        This object is available only if pyo is built with portmidi support
+        (see withPortmidi function).
+
+    >>> s = Server().boot()
+    >>> s.deactivateMidi()
+    >>> dispatch = MidiDispatcher(5)
+    >>> dispatch.start()
+    >>> dispatch.send(144, 60, 127)
+
+    """
+    def __init__(self, mididev=-1):
+        threading.Thread.__init__(self)
+        self.daemon = True
+        self._mididev = mididev
+        if type(mididev) is not list:
+            mididev = [mididev]
+        self._dispatcher = MidiDispatcher_base(mididev)
+
+    def run(self):
+        """
+        Starts the process. The thread runs as daemon, so no need to stop it.
+
+        """
+        self._dispatcher.play()
+        while True:
+            try:
+                time.sleep(0.001)
+            except:
+                pass
+
+    def send(self, status, data1, data2=0, timestamp=0, device=-1):
+        """
+        Send a MIDI message to the selected midi output device.
+
+        Arguments can be list of values to generate multiple events
+        in one call.
+
+        :Args:
+
+            status: int
+                Status byte.
+            data1: int
+                First data byte.
+            data2: int, optional
+                Second data byte. Defaults to 0.
+            timestamp: int, optional
+                The delay time, in milliseconds, before the note
+                is sent on the portmidi stream. A value of 0 means
+                to play the note now. Defaults to 0.
+            device: int, optional
+                The index of the device to which the message will
+                be sent. The default (-1) means all devices. See
+                `getDeviceInfos()` to retrieve device indexes.
+
+        """
+        status, data1, data2, timestamp, device, lmax = convertArgsToLists(status, data1, data2, timestamp, device)
+        [self._dispatcher.send(wrap(status,i), wrap(data1,i), wrap(data2,i), wrap(timestamp,i), wrap(device,i)) for i in range(lmax)]
+
+    def getDeviceInfos(self):
+        """
+        Returns infos about connected midi devices.
+
+        This method returns a list of dictionaries, one per device.
+
+        Dictionary format is:
+
+        {"id": device_id (int), "name": device_name (str), "interface": interface (str)}
+
+        """
+        infos = self._dispatcher.getDeviceInfos()
+        if infos:
+            lst = []
+            for info in infos:
+                dct = {}
+                items = info.split(", ")
+                for item in items:
+                    isplit = item.split(": ")
+                    dct[isplit[0]] = isplit[1]
+                dct["id"] = int(dct["id"])
+                lst.append(dct)
+            return lst
+        return []
+
 OscListenerLock = threading.Lock()
 
 class OscListener(threading.Thread):
diff --git a/pyolib/matrixprocess.py b/pyolib/matrixprocess.py
index 6b971b3..0c02422 100644
--- a/pyolib/matrixprocess.py
+++ b/pyolib/matrixprocess.py
@@ -205,6 +205,7 @@ class MatrixRecLoop(PyoObject):
         in_fader, matrix, lmax = convertArgsToLists(self._in_fader, matrix)
         self._base_objs = [MatrixRecLoop_base(wrap(in_fader,i), wrap(matrix,i)) for i in range(len(matrix))]
         self._trig_objs = Dummy([TriggerDummy_base(obj) for obj in self._base_objs])
+        self.play()
 
     def out(self, chnl=0, inc=1, dur=0, delay=0):
         return self.play(dur, delay)
@@ -298,6 +299,7 @@ class MatrixPointer(PyoObject):
         self._y = y
         matrix, x, y, mul, add, lmax = convertArgsToLists(matrix, x, y, mul, add)
         self._base_objs = [MatrixPointer_base(wrap(matrix,i), wrap(x,i), wrap(y,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setMatrix(self, x):
         """
@@ -420,6 +422,7 @@ class MatrixMorph(PyoObject):
         in_fader, matrix, lmax = convertArgsToLists(self._in_fader, matrix)
         self._base_sources = [source[0] for source in sources]
         self._base_objs = [MatrixMorph_base(wrap(in_fader,i), wrap(matrix,i), self._base_sources) for i in range(len(matrix))]
+        self.play()
 
     def out(self, chnl=0, inc=1, dur=0, delay=0):
         return self.play(dur, delay)
diff --git a/pyolib/midi.py b/pyolib/midi.py
index 549234d..be9e7c3 100644
--- a/pyolib/midi.py
+++ b/pyolib/midi.py
@@ -80,6 +80,7 @@ class Midictl(PyoObject):
         self._channel = channel
         ctlnumber, minscale, maxscale, init, channel, mul, add, lmax = convertArgsToLists(ctlnumber, minscale, maxscale, init, channel, mul, add)
         self._base_objs = [Midictl_base(wrap(ctlnumber,i), wrap(minscale,i), wrap(maxscale,i), wrap(init,i), wrap(channel,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def out(self, chnl=0, inc=1, dur=0, delay=0):
         return self.play(dur, delay)
@@ -160,7 +161,7 @@ class Midictl(PyoObject):
 
     def setInterpolation(self, x):
         """
-        Activate/Deactivate interpolation. Activated by default.
+        Activate/Deactivate interpolation. Off by default.
 
         :Args:
 
@@ -255,6 +256,7 @@ class CtlScan(PyoObject):
         self._function = WeakMethod(function)
         self._toprint = toprint
         self._base_objs = [CtlScan_base(self._function, self._toprint)]
+        self.play()
 
     def out(self, chnl=0, inc=1, dur=0, delay=0):
         return self.play(dur, delay)
@@ -366,6 +368,7 @@ class CtlScan2(PyoObject):
         self._function = WeakMethod(function)
         self._toprint = toprint
         self._base_objs = [CtlScan2_base(self._function, self._toprint)]
+        self.play()
 
     def out(self, chnl=0, inc=1, dur=0, delay=0):
         return self.play(dur, delay)
@@ -514,6 +517,7 @@ class Notein(PyoObject):
             self._base_objs.append(Notein_base(self._base_handler, i, 1, wrap(mul,i), wrap(add,i)))
             self._trig_objs.append(NoteinTrig_base(self._base_handler, i, 0, 1, 0))
             self._trig_objs.append(NoteinTrig_base(self._base_handler, i, 1, 1, 0))
+        self.play()
 
     def __getitem__(self, str):
         if str == 'pitch':
@@ -740,6 +744,7 @@ class Bendin(PyoObject):
         self._channel = channel
         brange, scale, channel, mul, add, lmax = convertArgsToLists(brange, scale, channel, mul, add)
         self._base_objs = [Bendin_base(wrap(brange,i), wrap(scale,i), wrap(channel,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def out(self, chnl=0, inc=1, dur=0, delay=0):
         return self.play(dur, delay)
@@ -789,6 +794,20 @@ class Bendin(PyoObject):
         x, lmax = convertArgsToLists(x)
         [obj.setChannel(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
+    def setInterpolation(self, x):
+        """
+        Activate/Deactivate interpolation. Off by default.
+
+        :Args:
+
+            x: boolean
+                True activates the interpolation, False deactivates it.
+
+        """
+        pyoArgsAssert(self, "b", x)
+        x, lmax = convertArgsToLists(x)
+        [obj.setInterpolation(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
         self._map_list = [SLMap(0.0, 12.0, 'lin', 'brange', self._brange, dataOnly=True),
                          SLMap(0, 1, 'lin', 'scale', self._scale, res="int", dataOnly=True),
@@ -860,6 +879,7 @@ class Touchin(PyoObject):
         self._channel = channel
         minscale, maxscale, init, channel, mul, add, lmax = convertArgsToLists(minscale, maxscale, init, channel, mul, add)
         self._base_objs = [Touchin_base(wrap(minscale,i), wrap(maxscale,i), wrap(init,i), wrap(channel,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def out(self, chnl=0, inc=1, dur=0, delay=0):
         return self.play(dur, delay)
@@ -909,6 +929,20 @@ class Touchin(PyoObject):
         x, lmax = convertArgsToLists(x)
         [obj.setChannel(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
+    def setInterpolation(self, x):
+        """
+        Activate/Deactivate interpolation. Off by default.
+
+        :Args:
+
+            x: boolean
+                True activates the interpolation, False deactivates it.
+
+        """
+        pyoArgsAssert(self, "b", x)
+        x, lmax = convertArgsToLists(x)
+        [obj.setInterpolation(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
         self._map_list = [SLMap(-1.0, 0.0, 'lin', 'minscale', self._minscale, dataOnly=True),
                          SLMap(0.0, 1.0, 'lin', 'maxscale', self._maxscale, dataOnly=True),
@@ -974,6 +1008,7 @@ class Programin(PyoObject):
         self._channel = channel
         channel, mul, add, lmax = convertArgsToLists(channel, mul, add)
         self._base_objs = [Programin_base(wrap(channel,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def out(self, chnl=0, inc=1, dur=0, delay=0):
         return self.play(dur, delay)
@@ -1061,6 +1096,7 @@ class MidiAdsr(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, attack, decay, sustain, release, mul, add, lmax = convertArgsToLists(self._in_fader, attack, decay, sustain, release, mul, add)
         self._base_objs = [MidiAdsr_base(wrap(in_fader,i), wrap(attack,i), wrap(decay,i), wrap(sustain,i), wrap(release,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def out(self, chnl=0, inc=1, dur=0, delay=0):
         return self.play(dur, delay)
@@ -1265,6 +1301,7 @@ class MidiDelAdsr(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, delay, attack, decay, sustain, release, mul, add, lmax = convertArgsToLists(self._in_fader, delay, attack, decay, sustain, release, mul, add)
         self._base_objs = [MidiDelAdsr_base(wrap(in_fader,i), wrap(delay,i), wrap(attack,i), wrap(decay,i), wrap(sustain,i), wrap(release,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def out(self, chnl=0, inc=1, dur=0, delay=0):
         return self.play(dur, delay)
@@ -1469,6 +1506,7 @@ class RawMidi(PyoObject):
         PyoObject.__init__(self)
         self._function = WeakMethod(function)
         self._base_objs = [RawMidi_base(self._function)]
+        self.play()
 
     def out(self, chnl=0, inc=1, dur=0, delay=0):
         return self.play(dur, delay)
diff --git a/pyolib/opensndctrl.py b/pyolib/opensndctrl.py
index 4860b01..9406a82 100644
--- a/pyolib/opensndctrl.py
+++ b/pyolib/opensndctrl.py
@@ -96,6 +96,7 @@ class OscSend(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, port, address, host, lmax = convertArgsToLists(self._in_fader, port, address, host)
         self._base_objs = [OscSend_base(wrap(in_fader,i), wrap(port,i), wrap(address,i), wrap(host,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -192,6 +193,7 @@ class OscReceive(PyoObject):
         self._address = address
         self._mainReceiver = OscReceiver_base(port, address)
         self._base_objs = [OscReceive_base(self._mainReceiver, wrap(address,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def __getitem__(self, i):
         if type(i) in [bytes_t, unicode_t]:
@@ -387,6 +389,7 @@ class OscDataSend(PyoObject):
         self._addresses = {}
         for i, adr in enumerate(address):
             self._addresses[adr] = self._base_objs[i]
+        self.play()
 
     def out(self, chnl=0, inc=1, dur=0, delay=0):
         return self.play(dur, delay)
@@ -552,6 +555,7 @@ class OscDataReceive(PyoObject):
         self._address, lmax = convertArgsToLists(address)
         # self._address is linked with list at C level
         self._base_objs = [OscDataReceive_base(port, self._address, self._function)]
+        self.play()
 
     def setMul(self, x):
         pass
@@ -658,6 +662,7 @@ class OscListReceive(PyoObject):
         self._address = address
         self._mainReceiver = OscListReceiver_base(port, address, num)
         self._base_objs = [OscListReceive_base(self._mainReceiver, wrap(address,i), j, wrap(mul,i), wrap(add,i)) for i in range(lmax) for j in range(self._num)]
+        self.play()
 
     def __getitem__(self, i):
         if type(i) in [bytes_t, unicode_t]:
diff --git a/pyolib/pan.py b/pyolib/pan.py
index a48549f..683b4ef 100644
--- a/pyolib/pan.py
+++ b/pyolib/pan.py
@@ -71,6 +71,7 @@ class Pan(PyoObject):
         for i in range(lmax):
             for j in range(outs):
                 self._base_objs.append(Pan_base(wrap(self._base_players,i), j, wrap(mul,i), wrap(add,i)))
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -182,6 +183,7 @@ class SPan(PyoObject):
         for i in range(lmax):
             for j in range(outs):
                 self._base_objs.append(SPan_base(wrap(self._base_players,i), j, wrap(mul,i), wrap(add,i)))
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -278,6 +280,7 @@ class Switch(PyoObject):
         for j in range(outs):
             for i in range(lmax):
                 self._base_objs.append(Switch_base(wrap(self._base_players,i), j, wrap(mul,i), wrap(add,i)))
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -376,6 +379,7 @@ class Selector(PyoObject):
                     except:
                         choice.append(obj)
                 self._base_objs.append(Selector_base(choice, wrap(voice,i), wrap(mul,i), wrap(add,i)))
+        self.play()
 
     def setInputs(self, x):
         """
@@ -494,6 +498,7 @@ class VoiceManager(PyoObject):
         else:
             t_streams = None
         self._base_objs = [VoiceManager_base(wrap(in_fader,i), t_streams, wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -604,6 +609,7 @@ class Mixer(PyoObject):
         time, mul, add, lmax = convertArgsToLists(time, mul, add)
         self._base_players = [Mixer_base(outs, wrap(time,i)) for i in range(chnls)]
         self._base_objs = [MixerVoice_base(self._base_players[j], i, wrap(mul,i), wrap(add,i)) for i in range(outs) for j in range(chnls)]
+        self.play()
 
     def __getitem__(self, x):
         if type(x) == slice:
diff --git a/pyolib/pattern.py b/pyolib/pattern.py
index fd07313..63ce461 100644
--- a/pyolib/pattern.py
+++ b/pyolib/pattern.py
@@ -221,6 +221,7 @@ class Score(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, fname, lmax = convertArgsToLists(self._in_fader, fname)
         self._base_objs = [Score_base(wrap(in_fader,i), wrap(fname,i)) for i in range(lmax)]
+        self.play()
 
     def out(self, chnl=0, inc=1, dur=0, delay=0):
         return self.play(dur, delay)
@@ -304,6 +305,7 @@ class CallAfter(PyoObject):
         self._function = getWeakMethodRef(function)
         function, time, arg, lmax = convertArgsToLists(function, time, arg)
         self._base_objs = [CallAfter_base(WeakMethod(wrap(function,i)), wrap(time,i), wrap(arg,i)) for i in range(lmax)]
+        self.play()
 
     def out(self, x=0, inc=1, dur=0, delay=0):
         return self.play(dur, delay)
diff --git a/pyolib/phasevoc.py b/pyolib/phasevoc.py
index 7997797..0bc1774 100644
--- a/pyolib/phasevoc.py
+++ b/pyolib/phasevoc.py
@@ -92,6 +92,7 @@ class PVAnal(PyoPVObject):
         self._in_fader = InputFader(input)
         in_fader, size, overlaps, wintype, lmax = convertArgsToLists(self._in_fader, size, overlaps, wintype)
         self._base_objs = [PVAnal_base(wrap(in_fader,i), wrap(size,i), wrap(overlaps,i), wrap(wintype,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -223,6 +224,7 @@ class PVSynth(PyoObject):
         self._wintype = wintype
         input, wintype, mul, add, lmax = convertArgsToLists(self._input, wintype, mul, add)
         self._base_objs = [PVSynth_base(wrap(input,i), wrap(wintype,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x):
         """
@@ -317,6 +319,7 @@ class PVAddSynth(PyoObject):
         self._inc = inc
         input, pitch, num, first, inc, mul, add, lmax = convertArgsToLists(self._input, pitch, num, first, inc, mul, add)
         self._base_objs = [PVAddSynth_base(wrap(input,i), wrap(pitch,i), wrap(num,i), wrap(first,i), wrap(inc,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x):
         """
@@ -462,6 +465,7 @@ class PVTranspose(PyoPVObject):
         self._transpo = transpo
         input, transpo, lmax = convertArgsToLists(self._input, transpo)
         self._base_objs = [PVTranspose_base(wrap(input,i), wrap(transpo,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x):
         """
@@ -547,6 +551,7 @@ class PVVerb(PyoPVObject):
         self._damp = damp
         input, revtime, damp, lmax = convertArgsToLists(self._input, revtime, damp)
         self._base_objs = [PVVerb_base(wrap(input,i), wrap(revtime,i), wrap(damp,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x):
         """
@@ -657,6 +662,7 @@ class PVGate(PyoPVObject):
         self._inverse = inverse
         input, thresh, damp, inverse, lmax = convertArgsToLists(self._input, thresh, damp, inverse)
         self._base_objs = [PVGate_base(wrap(input,i), wrap(thresh,i), wrap(damp,i), wrap(inverse,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x):
         """
@@ -806,6 +812,7 @@ class PVCross(PyoPVObject):
         self._fade = fade
         input, input2, fade, lmax = convertArgsToLists(self._input, self._input2, fade)
         self._base_objs = [PVCross_base(wrap(input,i), wrap(input2,i), wrap(fade,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x):
         """
@@ -924,6 +931,7 @@ class PVMult(PyoPVObject):
         self._input2 = input2
         input, input2, lmax = convertArgsToLists(self._input, self._input2)
         self._base_objs = [PVMult_base(wrap(input,i), wrap(input2,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x):
         """
@@ -1024,6 +1032,7 @@ class PVMorph(PyoPVObject):
         self._fade = fade
         input, input2, fade, lmax = convertArgsToLists(self._input, self._input2, fade)
         self._base_objs = [PVMorph_base(wrap(input,i), wrap(input2,i), wrap(fade,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x):
         """
@@ -1140,6 +1149,7 @@ class PVFilter(PyoPVObject):
         self._mode = mode
         input, table, gain, mode, lmax = convertArgsToLists(self._input, table, gain, mode)
         self._base_objs = [PVFilter_base(wrap(input,i), wrap(table,i), wrap(gain,i), wrap(mode,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x):
         """
@@ -1293,6 +1303,7 @@ class PVDelay(PyoPVObject):
         self._mode = mode
         input, deltable, feedtable, maxdelay, mode, lmax = convertArgsToLists(self._input, deltable, feedtable, maxdelay, mode)
         self._base_objs = [PVDelay_base(wrap(input,i), wrap(deltable,i), wrap(feedtable,i), wrap(maxdelay,i), wrap(mode,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x):
         """
@@ -1429,6 +1440,7 @@ class PVBuffer(PyoPVObject):
         self._length = length
         input, index, pitch, length, lmax = convertArgsToLists(self._input, index, pitch, length)
         self._base_objs = [PVBuffer_base(wrap(input,i), wrap(index,i), wrap(pitch,i), wrap(length,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x):
         """
@@ -1531,6 +1543,7 @@ class PVShift(PyoPVObject):
         self._shift = shift
         input, shift, lmax = convertArgsToLists(self._input, shift)
         self._base_objs = [PVShift_base(wrap(input,i), wrap(shift,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x):
         """
@@ -1608,6 +1621,16 @@ class PVAmpMod(PyoPVObject):
         spread: float or PyoObject, optional
             Spreading factor for oscillator frequencies, between
             -1 and 1. 0 means every oscillator has the same frequency.
+        shape: int, optional
+            Modulation oscillator waveform. Possible shapes are:
+                0. Sine (default)
+                1. Sawtooth
+                2. Ramp (inverse sawtooth)
+                3. Square
+                4. Triangle
+                5. Brown Noise
+                6. Pink Noise
+                7. White Noise
 
     >>> s = Server().boot()
     >>> s.start()
@@ -1617,14 +1640,16 @@ class PVAmpMod(PyoPVObject):
     >>> pvs = PVSynth(pvm).out()
 
     """
-    def __init__(self, input, basefreq=1, spread=0):
-        pyoArgsAssert(self, "pOO", input, basefreq, spread)
+    def __init__(self, input, basefreq=1, spread=0, shape=0):
+        pyoArgsAssert(self, "pOOi", input, basefreq, spread, shape)
         PyoPVObject.__init__(self)
         self._input = input
         self._basefreq = basefreq
         self._spread = spread
-        input, basefreq, spread, lmax = convertArgsToLists(self._input, basefreq, spread)
-        self._base_objs = [PVAmpMod_base(wrap(input,i), wrap(basefreq,i), wrap(spread,i)) for i in range(lmax)]
+        self._shape = shape
+        input, basefreq, spread, shape, lmax = convertArgsToLists(self._input, basefreq, spread, shape)
+        self._base_objs = [PVAmpMod_base(wrap(input,i), wrap(basefreq,i), wrap(spread,i), wrap(shape,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x):
         """
@@ -1671,6 +1696,29 @@ class PVAmpMod(PyoPVObject):
         x, lmax = convertArgsToLists(x)
         [obj.setSpread(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
+    def setShape(self, x):
+        """
+        Replace the `shape` attribute.
+
+        :Args:
+
+            x: int
+                new `shape` attribute. Possible shapes are:
+                    0. Sine (default)
+                    1. Sawtooth
+                    2. Ramp (inverse sawtooth)
+                    3. Square
+                    4. Triangle
+                    5. Brown Noise
+                    6. Pink Noise
+                    7. White Noise
+
+        """
+        pyoArgsAssert(self, "i", x)
+        self._shape = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setShape(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+
     def reset(self):
         """
         Resets modulation pointers to 0.
@@ -1704,6 +1752,13 @@ class PVAmpMod(PyoPVObject):
     @spread.setter
     def spread(self, x): self.setSpread(x)
 
+    @property
+    def shape(self):
+        """int. Modulation oscillator waveform."""
+        return self._shape
+    @shape.setter
+    def shape(self, x): self.setShape(x)
+
 class PVFreqMod(PyoPVObject):
     """
     Performs frequency independent frequency modulations.
@@ -1735,6 +1790,16 @@ class PVFreqMod(PyoPVObject):
         depth: float or PyoObject, optional
             Amplitude of the modulating oscillators, between 0 and 1.
             Defaults to 0.1.
+        shape: int, optional
+            Modulation oscillator waveform. Possible shapes are:
+                0. Sine (default)
+                1. Sawtooth
+                2. Ramp (inverse sawtooth)
+                3. Square
+                4. Triangle
+                5. Brown Noise
+                6. Pink Noise
+                7. White Noise
 
     >>> s = Server().boot()
     >>> s.start()
@@ -1744,15 +1809,17 @@ class PVFreqMod(PyoPVObject):
     >>> pvs = PVSynth(pvm).out()
 
     """
-    def __init__(self, input, basefreq=1, spread=0, depth=0.1):
-        pyoArgsAssert(self, "pOOO", input, basefreq, spread, depth)
+    def __init__(self, input, basefreq=1, spread=0, depth=0.1, shape=0):
+        pyoArgsAssert(self, "pOOOi", input, basefreq, spread, depth, shape)
         PyoPVObject.__init__(self)
         self._input = input
         self._basefreq = basefreq
         self._spread = spread
         self._depth = depth
-        input, basefreq, spread, depth, lmax = convertArgsToLists(self._input, basefreq, spread, depth)
-        self._base_objs = [PVFreqMod_base(wrap(input,i), wrap(basefreq,i), wrap(spread,i), wrap(depth,i)) for i in range(lmax)]
+        self._shape = shape
+        input, basefreq, spread, depth, shape, lmax = convertArgsToLists(self._input, basefreq, spread, depth, shape)
+        self._base_objs = [PVFreqMod_base(wrap(input,i), wrap(basefreq,i), wrap(spread,i), wrap(depth,i), wrap(shape,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x):
         """
@@ -1814,6 +1881,29 @@ class PVFreqMod(PyoPVObject):
         x, lmax = convertArgsToLists(x)
         [obj.setDepth(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
+    def setShape(self, x):
+        """
+        Replace the `shape` attribute.
+
+        :Args:
+
+            x: int
+                new `shape` attribute. Possible shapes are:
+                    0. Sine (default)
+                    1. Sawtooth
+                    2. Ramp (inverse sawtooth)
+                    3. Square
+                    4. Triangle
+                    5. Brown Noise
+                    6. Pink Noise
+                    7. White Noise
+
+        """
+        pyoArgsAssert(self, "i", x)
+        self._shape = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setShape(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+
     def reset(self):
         """
         Resets modulation pointers to 0.
@@ -1855,6 +1945,13 @@ class PVFreqMod(PyoPVObject):
     @depth.setter
     def depth(self, x): self.setDepth(x)
 
+    @property
+    def shape(self):
+        """int. Modulation oscillator waveform."""
+        return self._shape
+    @shape.setter
+    def shape(self, x): self.setShape(x)
+
 class PVBufLoops(PyoPVObject):
     """
     Phase vocoder buffer with bin independent speed playback.
@@ -1912,6 +2009,7 @@ class PVBufLoops(PyoPVObject):
         self._length = length
         input, low, high, mode, length, lmax = convertArgsToLists(self._input, low, high, mode, length)
         self._base_objs = [PVBufLoops_base(wrap(input,i), wrap(low,i), wrap(high,i), wrap(mode,i), wrap(length,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x):
         """
@@ -2057,6 +2155,7 @@ class PVBufTabLoops(PyoPVObject):
         self._length = length
         input, speed, length, lmax = convertArgsToLists(self._input, speed, length)
         self._base_objs = [PVBufTabLoops_base(wrap(input,i), wrap(speed,i), wrap(length,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x):
         """
@@ -2154,6 +2253,7 @@ class PVMix(PyoPVObject):
         self._input2 = input2
         input, input2, lmax = convertArgsToLists(self._input, self._input2)
         self._base_objs = [PVMix_base(wrap(input,i), wrap(input2,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x):
         """
diff --git a/pyolib/players.py b/pyolib/players.py
index 8d4bd42..cde1780 100644
--- a/pyolib/players.py
+++ b/pyolib/players.py
@@ -112,6 +112,7 @@ class SfPlayer(PyoObject):
                 self._base_objs.append(SfPlay_base(self._base_players[-1], j, wrap(mul,i), wrap(add,i)))
                 _trig_objs_tmp.append(TriggerDummy_base(self._base_players[-1]))
         self._trig_objs = Dummy(_trig_objs_tmp)
+        self.play()
 
     def setPath(self, path):
         """
@@ -337,6 +338,7 @@ class SfMarkerShuffler(PyoObject):
         for i in range(lmax * self._snd_chnls):
             j = i // self._snd_chnls
             self._base_objs.append(SfMarkerShuffle_base(wrap(self._base_players,j), i % self._snd_chnls, wrap(mul,j), wrap(add,j)))
+        self.play()
 
     def setSpeed(self, x):
         """
@@ -464,6 +466,7 @@ class SfMarkerLooper(PyoObject):
         for i in range(lmax * self._snd_chnls):
             j = i // self._snd_chnls
             self._base_objs.append(SfMarkerLoop_base(wrap(self._base_players,j), i % self._snd_chnls, wrap(mul,j), wrap(add,j)))
+        self.play()
 
     def setSpeed(self, x):
         """
diff --git a/pyolib/randoms.py b/pyolib/randoms.py
index c39e6a0..a864aaa 100644
--- a/pyolib/randoms.py
+++ b/pyolib/randoms.py
@@ -59,6 +59,7 @@ class Randi(PyoObject):
         self._freq = freq
         min, max, freq, mul, add, lmax = convertArgsToLists(min, max, freq, mul, add)
         self._base_objs = [Randi_base(wrap(min,i), wrap(max,i), wrap(freq,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setMin(self, x):
         """
@@ -168,6 +169,7 @@ class Randh(PyoObject):
         self._freq = freq
         min, max, freq, mul, add, lmax = convertArgsToLists(min, max, freq, mul, add)
         self._base_objs = [Randh_base(wrap(min,i), wrap(max,i), wrap(freq,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setMin(self, x):
         """
@@ -279,6 +281,7 @@ class Choice(PyoObject):
             choicelen = len(choice)
             lmax = max(choicelen, lmax)
             self._base_objs = [Choice_base(wrap(choice,i), wrap(freq,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setChoice(self, x):
         """
@@ -362,6 +365,7 @@ class RandInt(PyoObject):
         self._freq = freq
         max, freq, mul, add, lmax = convertArgsToLists(max, freq, mul, add)
         self._base_objs = [RandInt_base(wrap(max,i), wrap(freq,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setMax(self, x):
         """
@@ -448,6 +452,7 @@ class RandDur(PyoObject):
         self._max = max
         min, max, mul, add, lmax = convertArgsToLists(min, max, mul, add)
         self._base_objs = [RandDur_base(wrap(min,i), wrap(max,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setMin(self, x):
         """
@@ -600,6 +605,7 @@ class Xnoise(PyoObject):
         for i, t in enumerate(dist):
             if type(t) in [bytes_t, unicode_t]: dist[i] = XNOISE_DICT.get(t, 0)
         self._base_objs = [Xnoise_base(wrap(dist,i), wrap(freq,i), wrap(x1,i), wrap(x2,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setDist(self, x):
         """
@@ -813,6 +819,7 @@ class XnoiseMidi(PyoObject):
         for i, t in enumerate(dist):
             if type(t) in [bytes_t, unicode_t]: dist[i] = XNOISE_DICT.get(t, 0)
         self._base_objs = [XnoiseMidi_base(wrap(dist,i), wrap(freq,i), wrap(x1,i), wrap(x2,i), wrap(scale,i), wrap(mrange,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setDist(self, x):
         """
@@ -1065,6 +1072,7 @@ class XnoiseDur(PyoObject):
         for i, t in enumerate(dist):
             if type(t) in [bytes_t, unicode_t]: dist[i] = XNOISE_DICT.get(t, 0)
         self._base_objs = [XnoiseDur_base(wrap(dist,i), wrap(min,i), wrap(max,i), wrap(x1,i), wrap(x2,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setDist(self, x):
         """
@@ -1229,6 +1237,7 @@ class Urn(PyoObject):
         max, freq, mul, add, lmax = convertArgsToLists(max, freq, mul, add)
         self._base_objs = [Urn_base(wrap(max,i), wrap(freq,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
         self._trig_objs = Dummy([TriggerDummy_base(obj) for obj in self._base_objs])
+        self.play()
 
     def out(self, chnl=0, inc=1, dur=0, delay=0):
         return self
@@ -1331,6 +1340,7 @@ class LogiMap(PyoObject):
         self._freq = freq
         chaos, freq, init, mul, add, lmax = convertArgsToLists(chaos, freq, init, mul, add)
         self._base_objs = [LogiMap_base(wrap(chaos,i), wrap(freq,i), wrap(init,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def out(self, chnl=0, inc=1, dur=0, delay=0):
         return self
diff --git a/pyolib/server.py b/pyolib/server.py
index cce7050..63ea0e5 100644
--- a/pyolib/server.py
+++ b/pyolib/server.py
@@ -460,6 +460,36 @@ class Server(object):
         self._verbosity = x
         self._server.setVerbosity(x)
 
+    def setGlobalDur(self, x):
+        """
+        Set the global object duration (time to wait before stopping the object).
+
+        This value, if not 0, will override the `dur` argument of object's
+        play() and out() methods.
+
+        :Args:
+
+            x: float
+                New global duration.
+
+        """
+        self._server.setGlobalDur(x)
+
+    def setGlobalDel(self, x):
+        """
+        Set the global object delay time (time to wait before activating the object).
+
+        This value, if not 0, will override the `del` argument of object's
+        play() and out() methods.
+
+        :Args:
+
+            x: float
+                New global delay time.
+
+        """
+        self._server.setGlobalDel(x)
+
     def setJackAuto(self, xin=True, xout=True):
         """
         Tells the server to auto-connect (or not) Jack ports to System ports.
@@ -964,6 +994,20 @@ class Server(object):
         """
         return self._server.getBufferSize()
 
+    def getGlobalDur(self):
+        """
+        Return the current global duration.
+
+        """
+        return self._server.getGlobalDur()
+
+    def getGlobalDel(self):
+        """
+        Return the current global delay time.
+
+        """
+        return self._server.getGlobalDel()
+
     def getGlobalSeed(self):
         """
         Return the current global seed.
diff --git a/pyolib/tableprocess.py b/pyolib/tableprocess.py
index e7c78aa..a897006 100644
--- a/pyolib/tableprocess.py
+++ b/pyolib/tableprocess.py
@@ -70,6 +70,7 @@ class Osc(PyoObject):
         self._interp = interp
         table, freq, phase, interp, mul, add, lmax = convertArgsToLists(table, freq, phase, interp, mul, add)
         self._base_objs = [Osc_base(wrap(table,i), wrap(freq,i), wrap(phase,i), wrap(interp,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setTable(self, x):
         """
@@ -213,6 +214,7 @@ class OscLoop(PyoObject):
         self._feedback = feedback
         table, freq, feedback, mul, add, lmax = convertArgsToLists(table, freq, feedback, mul, add)
         self._base_objs = [OscLoop_base(wrap(table,i), wrap(freq,i), wrap(feedback,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setTable(self, x):
         """
@@ -333,6 +335,7 @@ class OscTrig(PyoObject):
         self._interp = interp
         table, trig, freq, phase, interp, mul, add, lmax = convertArgsToLists(table, trig, freq, phase, interp, mul, add)
         self._base_objs = [OscTrig_base(wrap(table,i), wrap(trig,i), wrap(freq,i), wrap(phase,i), wrap(interp,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setTable(self, x):
         """
@@ -549,6 +552,7 @@ class OscBank(PyoObject):
         self._num = num
         table, freq, spread, slope, frndf, frnda, arndf, arnda, num, fjit, mul, add, lmax = convertArgsToLists(table, freq, spread, slope, frndf, frnda, arndf, arnda, num, fjit, mul, add)
         self._base_objs = [OscBank_base(wrap(table,i), wrap(freq,i), wrap(spread,i), wrap(slope,i), wrap(frndf,i), wrap(frnda,i), wrap(arndf,i), wrap(arnda,i), wrap(num,i), wrap(fjit,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setTable(self, x):
         """
@@ -976,6 +980,7 @@ class Pulsar(PyoObject):
         self._interp = interp
         table, env, freq, frac, phase, interp, mul, add, lmax = convertArgsToLists(table, env, freq, frac, phase, interp, mul, add)
         self._base_objs = [Pulsar_base(wrap(table,i), wrap(env,i), wrap(freq,i), wrap(frac,i), wrap(phase,i), wrap(interp,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setTable(self, x):
         """
@@ -1149,6 +1154,7 @@ class Pointer(PyoObject):
         self._index = index
         table, index, mul, add, lmax = convertArgsToLists(table, index, mul, add)
         self._base_objs = [Pointer_base(wrap(table,i), wrap(index,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setTable(self, x):
         """
@@ -1240,6 +1246,7 @@ class Pointer2(PyoObject):
         self._autosmooth = autosmooth
         table, index, interp, autosmooth, mul, add, lmax = convertArgsToLists(table, index, interp, autosmooth, mul, add)
         self._base_objs = [Pointer2_base(wrap(table,i), wrap(index,i), wrap(interp,i), wrap(autosmooth,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setTable(self, x):
         """
@@ -1372,6 +1379,7 @@ class TableIndex(PyoObject):
         self._index = index
         table, index, mul, add, lmax = convertArgsToLists(table, index, mul, add)
         self._base_objs = [TableIndex_base(wrap(table,i), wrap(index,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setTable(self, x):
         """
@@ -1455,6 +1463,7 @@ class Lookup(PyoObject):
         self._index = index
         table, index, mul, add, lmax = convertArgsToLists(table, index, mul, add)
         self._base_objs = [Lookup_base(wrap(table,i), wrap(index,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setTable(self, x):
         """
@@ -1666,6 +1675,11 @@ class TableWrite(PyoObject):
             of the table). For any other value, the position must be
             in samples between 0 and the length of the table. Available
             at initialization time only.
+        maxwindow: int optional
+            Maximum length, in samples, of the interpolated window when
+            the position is moving fast. Useful to avoid interpolation
+            over the entire table if using a circular writing position.
+            Available at initialization time only. Defaults to 1024.
 
     .. note::
 
@@ -1687,16 +1701,18 @@ class TableWrite(PyoObject):
     >>> pat = Pattern(tab.refreshView, 0.05).play()
 
     """
-    def __init__(self, input, pos, table, mode=0):
-        pyoArgsAssert(self, "ooti", input, pos, table, mode)
+    def __init__(self, input, pos, table, mode=0, maxwindow=1024):
+        pyoArgsAssert(self, "ootii", input, pos, table, mode, maxwindow)
         PyoObject.__init__(self)
         self._input = input
         self._pos = pos
         self._table = table
         self._mode = mode
+        self._maxwindow = maxwindow
         self._in_fader = InputFader(input)
-        in_fader, pos, table, mode, lmax = convertArgsToLists(self._in_fader, pos, table, mode)
-        self._base_objs = [TableWrite_base(wrap(in_fader,i), wrap(pos,i), wrap(table,i), wrap(mode,i)) for i in range(len(table))]
+        in_fader, pos, table, mode, maxwindow, lmax = convertArgsToLists(self._in_fader, pos, table, mode, maxwindow)
+        self._base_objs = [TableWrite_base(wrap(in_fader,i), wrap(pos,i), wrap(table,i), wrap(mode,i), wrap(maxwindow,i)) for i in range(len(table))]
+        self.play()
 
     def out(self, chnl=0, inc=1, dur=0, delay=0):
         return self.play(dur, delay)
@@ -1821,6 +1837,7 @@ class TableMorph(PyoObject):
         in_fader, table, lmax = convertArgsToLists(self._in_fader, table)
         self._base_sources = [source[0] for source in sources]
         self._base_objs = [TableMorph_base(wrap(in_fader,i), wrap(table,i), self._base_sources) for i in range(len(table))]
+        self.play()
 
     def out(self, chnl=0, inc=1, dur=0, delay=0):
         return self.play(dur, delay)
@@ -1953,6 +1970,7 @@ class Granulator(PyoObject):
                                                                         pos, dur, grains, basedur, mul, add)
         self._base_objs = [Granulator_base(wrap(table,i), wrap(env,i), wrap(pitch,i), wrap(pos,i), wrap(dur,i),
                           wrap(grains,i), wrap(basedur,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setTable(self, x):
         """
@@ -2178,6 +2196,7 @@ class TrigTableRec(PyoObject):
         self._base_objs = [TrigTableRec_base(wrap(in_fader,i), wrap(in_fader2,i), wrap(table,i), wrap(fadetime,i)) for i in range(len(table))]
         self._trig_objs = Dummy([TriggerDummy_base(obj) for obj in self._base_objs])
         self._time_objs = [TrigTableRecTimeStream_base(obj) for obj in self._base_objs]
+        self.play()
 
     def __getitem__(self, i):
         if i == 'time':
@@ -2359,6 +2378,7 @@ class Looper(PyoObject):
             wrap(xfadeshape,i), wrap(startfromloop,i), wrap(interp,i), wrap(autosmooth,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
         self._trig_objs = Dummy([TriggerDummy_base(obj) for obj in self._base_objs])
         self._time_objs = [LooperTimeStream_base(obj) for obj in self._base_objs]
+        self.play()
 
     def __getitem__(self, i):
         if i == 'time':
@@ -2764,6 +2784,129 @@ class TablePut(PyoObject):
     @table.setter
     def table(self, x): self.setTable(x)
 
+class TableFill(PyoObject):
+    """
+    Continuously fills a table with incoming samples.
+
+    See :py:class:`DataTable` or :py:class:`NewTable` to create an empty table.
+
+    TableFill takes an audio input and writes values into a PyoTableObject,
+    samples by samples. It wraps around the table length when reaching the end
+    of the table.
+
+    Calling the play method reset the writing position to 0.
+
+    :Parent: :py:class:`PyoObject`
+
+    :Args:
+
+        input: PyoObject
+            Audio signal to write in the table.
+        table: PyoTableObject
+            The table where to write values.
+
+    .. note::
+
+        The out() method is bypassed. TableFill returns no signal.
+
+        TableFill has no `mul` and `add` attributes.
+
+    .. seealso::
+
+        :py:class:`TableWrite`, :py:class:`TablePut`, :py:class:`TableRec`
+
+    >>> s = Server().boot()
+    >>> s.start()
+    >>> table = DataTable(s.getBufferSize(), chnls=2)
+    >>> sig = Sine([400,500], mul=0.3)
+    >>> fill = TableFill(sig, table)
+    >>> read = TableRead(table, table.getRate(), loop=True).out()
+
+    """
+    def __init__(self, input, table):
+        pyoArgsAssert(self, "ot", input, table)
+        PyoObject.__init__(self)
+        self._input = input
+        self._table = table
+        self._in_fader = InputFader(input)
+        in_fader, table, lmax = convertArgsToLists(self._in_fader, table)
+        self._base_objs = [TableFill_base(wrap(in_fader,i), wrap(table,i)) for i in range(len(table))]
+        self.play()
+
+    def out(self, chnl=0, inc=1, dur=0, delay=0):
+        return self.play(dur, delay)
+
+    def setMul(self, x):
+        pass
+
+    def setAdd(self, x):
+        pass
+
+    def setInput(self, x, fadetime=0.05):
+        """
+        Replace the `input` attribute.
+
+        :Args:
+
+            x: PyoObject
+                New signal to process.
+            fadetime: float, optional
+                Crossfade time between old and new input. Defaults to 0.05.
+
+        """
+        pyoArgsAssert(self, "oN", x, fadetime)
+        self._input = x
+        self._in_fader.setInput(x, fadetime)
+
+    def setTable(self, x):
+        """
+        Replace the `table` attribute.
+
+        :Args:
+
+            x: PyoTableObject
+                new `table` attribute.
+
+        """
+        pyoArgsAssert(self, "t", x)
+        self._table = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setTable(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+
+    def getCurrentPos(self, all=False):
+        """
+        Returns the current pointer position, in samples, in the table.
+
+        :Args:
+
+            all: boolean, optional
+                If True, returns the current position of all
+                internal objects as a list.
+
+                If False, only the current position of the first object's 
+                stream will be returned as a float.
+
+        """
+        pyoArgsAssert(self, "B", all)
+        if not all:
+            return self._base_objs[0].getCurrentPos()
+        else:
+            return [obj.getCurrentPos() for obj in self._base_objs]
+
+    @property
+    def input(self):
+        """PyoObject. Audio signal to write in the table."""
+        return self._input
+    @input.setter
+    def input(self, x): self.setInput(x)
+
+    @property
+    def table(self):
+        """PyoTableObject. The table where to write values."""
+        return self._table
+    @table.setter
+    def table(self, x): self.setTable(x)
+
 class Granule(PyoObject):
     """
     Another granular synthesis generator.
@@ -2786,11 +2929,11 @@ class Granule(PyoObject):
             of `pitch` as its reading speed. Defaults to 1.
         pos: float or PyoObject, optional
             Pointer position, in samples, in the waveform table. Each
-            grain sampled the current value of this stream at the beginning
-            of its envelope and hold it until the end of the grain.
+            grain samples the current value of this stream at the beginning
+            of its envelope and holds it until the end of the grain.
             Defaults to 0.
         dur: float or PyoObject, optional
-            Duration, in seconds, of the grain. Each grain sampled the
+            Duration, in seconds, of the grain. Each grain samples the
             current value of this stream at the beginning of its envelope
             and hold it until the end of the grain. Defaults to 0.1.
 
@@ -2818,6 +2961,7 @@ class Granule(PyoObject):
         table, env, dens, pitch, pos, dur, mul, add, lmax = convertArgsToLists(table, env, dens, pitch, pos, dur, mul, add)
         self._base_objs = [Granule_base(wrap(table,i), wrap(env,i), wrap(dens,i), wrap(pitch,i), wrap(pos,i), wrap(dur,i),
                                            wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setTable(self, x):
         """
@@ -3011,6 +3155,7 @@ class TableScale(PyoObject):
         self._outtable = outtable
         table, outtable, mul, add, lmax = convertArgsToLists(table, outtable, mul, add)
         self._base_objs = [TableScale_base(wrap(table,i), wrap(outtable,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setTable(self, x):
         """
@@ -3075,27 +3220,27 @@ class Particle(PyoObject):
         dens: float or PyoObject, optional
             Density of grains per second. Defaults to 50.
         pitch: float or PyoObject, optional
-            Pitch of the grains. Each grain sampled the current value
-            of this stream at the beginning of its envelope and hold
+            Pitch of the grains. Each grain samples the current value
+            of this stream at the beginning of its envelope and holds
             it until the end of the grain. Defaults to 1.
         pos: float or PyoObject, optional
             Pointer position, in samples, in the waveform table. Each
             grain sampled the current value of this stream at the beginning
-            of its envelope and hold it until the end of the grain.
+            of its envelope and holds it until the end of the grain.
             Defaults to 0.
         dur: float or PyoObject, optional
-            Duration, in seconds, of the grain. Each grain sampled the
+            Duration, in seconds, of the grain. Each grain samples the
             current value of this stream at the beginning of its envelope
-            and hold it until the end of the grain. Defaults to 0.1.
+            and holds it until the end of the grain. Defaults to 0.1.
         dev: float or PyoObject, optional
             Maximum deviation of the starting time of the grain, between 0 and
-            1 (relative to the current duration of the grain). Each grain sampled
+            1 (relative to the current duration of the grain). Each grain samples
             the current value of this stream at the beginning of its envelope
-            and hold it until the end of the grain. Defaults to 0.01.
+            and holds it until the end of the grain. Defaults to 0.01.
         pan: float or PyoObject, optional
             Panning factor of the grain (if chnls=1, this value is skipped).
-            Each grain sampled the current value of this stream at the beginning
-            of its envelope and hold it until the end of the grain. Defaults to 0.5.
+            Each grain samples the current value of this stream at the beginning
+            of its envelope and holds it until the end of the grain. Defaults to 0.5.
         chnls: integer, optional
             Number of output channels per audio stream (if chnls=2 and a stereo sound
             table is given at the table argument, the objet will create 4 output
@@ -3138,6 +3283,7 @@ class Particle(PyoObject):
         for i in range(lmax):
             for j in range(chnls):
                 self._base_objs.append(Particle_base(wrap(self._base_players,i), j, wrap(mul,i), wrap(add,i)))
+        self.play()
 
     def setTable(self, x):
         """
@@ -3263,7 +3409,7 @@ class Particle(PyoObject):
         tablesize = self._table.getSize(False)
         self._map_list = [SLMap(1, 250, 'lin', 'dens', self._dens),
                           SLMap(0.25, 2., 'lin', 'pitch', self._pitch),
-                          SLMap(0, tablesize, 'lin', 'pos', self._pos),
+                          SLMap(0, tablesize, 'lin', 'pos', self._pos, res="int"),
                           SLMap(0.001, 1., 'lin', 'dur', self._dur),
                           SLMap(0., 1., 'lin', 'dev', self._dev),
                           SLMap(0., 1., 'lin', 'pan', self._pan),
@@ -3325,3 +3471,432 @@ class Particle(PyoObject):
         return self._pan
     @pan.setter
     def pan(self, x): self.setPan(x)
+
+class Particle2(PyoObject):
+    """
+    An even more full control granular synthesis generator.
+
+    This granulator object offers all the same controls as the
+    Particle object with additionally an independently controllable 
+    filter per grain. The filters use the same implementation as the
+    Biquad object.
+
+    :Parent: :py:class:`PyoObject`
+
+    :Args:
+
+        table: PyoTableObject
+            Table containing the waveform samples.
+        env: PyoTableObject
+            Table containing the grain envelope.
+        dens: float or PyoObject, optional
+            Density of grains per second. Defaults to 50.
+        pitch: float or PyoObject, optional
+            Pitch of the grains. Each grain samples the current value
+            of this stream at the beginning of its envelope and holds
+            it until the end of the grain. Defaults to 1.
+        pos: float or PyoObject, optional
+            Pointer position, in samples, in the waveform table. Each
+            grain samples the current value of this stream at the beginning
+            of its envelope and holds it until the end of the grain.
+            Defaults to 0.
+        dur: float or PyoObject, optional
+            Duration, in seconds, of the grain. Each grain samples the
+            current value of this stream at the beginning of its envelope
+            and holds it until the end of the grain. Defaults to 0.1.
+        dev: float or PyoObject, optional
+            Maximum deviation of the starting time of the grain, between 0 and
+            1 (relative to the current duration of the grain). Each grain samples
+            the current value of this stream at the beginning of its envelope
+            and holds it until the end of the grain. Defaults to 0.01.
+        pan: float or PyoObject, optional
+            Panning factor of the grain (if chnls=1, this value is skipped).
+            Each grain samples the current value of this stream at the beginning
+            of its envelope and holds it until the end of the grain. Defaults to 0.5.
+        filterfreq: float or PyoObject, optional
+            Center or cutoff frequency of the grain filter.
+            Each grain samples the current value of this stream at the beginning
+            of its envelope and hold it until the end of the grain. Defaults to 18000.
+        filterq: float or PyoObject, optional
+            Q of the grain filter.
+            Each grain samples the current value of this stream at the beginning
+            of its envelope and hold it until the end of the grain. Defaults to 0.7.
+        filtertype: float or PyoObject, optional
+            Type of the grain filter.
+            Each grain samples the current value of this stream at the beginning
+            of its envelope and hold it until the end of the grain. Thw value is
+            rounded to the nearest integer. Possible values are:
+                0. lowpass (default)
+                1. highpass
+                2. bandpass
+                3. bandstop
+                4. allpass
+
+        chnls: integer, optional
+            Number of output channels per audio stream (if chnls=2 and a stereo sound
+            table is given at the table argument, the objet will create 4 output
+            streams, 2 per table channel). Available at initialization only. Defaults to 1.
+
+    .. note::
+
+        Particle object compensate for the difference between sampling rate of the
+        loaded sound and the current sampling rate of the Server.
+
+    >>> s = Server().boot()
+    >>> s.start()
+    >>> snd = SndTable(SNDS_PATH+"/transparent.aif")
+    >>> end = snd.getSize() - s.getSamplingRate() * 0.25
+    >>> env = HannTable()
+    >>> dns = Randi(min=8, max=24, freq=.1)
+    >>> pit = Randh(min=0.49, max=0.51, freq=100)
+    >>> pos = Sine(0.05).range(0, end)
+    >>> dur = Randi(min=0.05, max=0.15, freq=0.15)
+    >>> dev = 0.001
+    >>> pan = Noise(0.5, 0.5)
+    >>> cf = Sine(0.07).range(75, 125)
+    >>> fcf = Choice(list(range(1, 40)), freq=150, mul=cf)
+    >>> grn = Particle2(snd, env, dns, pit, pos, dur, dev, pan, fcf, 20, 2, chnls=2, mul=.3)
+    >>> grn.out()
+
+    """
+    def __init__(self, table, env, dens=50, pitch=1, pos=0, dur=.1, dev=0.01, pan=0.5, filterfreq=18000, filterq=0.7, filtertype=0, chnls=1, mul=1, add=0):
+        pyoArgsAssert(self, "ttOOOOOOOOOIOO", table, env, dens, pitch, pos, dur, dev, pan, filterfreq, filterq, filtertype, chnls, mul, add)
+        PyoObject.__init__(self, mul, add)
+        self._table = table
+        self._env = env
+        self._dens = dens
+        self._pitch = pitch
+        self._pos = pos
+        self._dur = dur
+        self._dev = dev
+        self._pan = pan
+        self._filterfreq = filterfreq
+        self._filterq = filterq
+        self._filtertype = filtertype
+        self._chnls = chnls
+        table, env, dens, pitch, pos, dur, dev, pan, filterfreq, filterq, filtertype, mul, add, lmax = convertArgsToLists(table, env, dens, pitch, pos, dur, dev, pan, filterfreq, filterq, filtertype, mul, add)
+        self._base_players = [MainParticle2_base(wrap(table,i), wrap(env,i), wrap(dens,i), wrap(pitch,i), wrap(pos,i), wrap(dur,i), wrap(dev,i), wrap(pan,i), wrap(filterfreq,i), wrap(filterq,i), wrap(filtertype,i), chnls) for i in range(lmax)]
+        self._base_objs = []
+        for i in range(lmax):
+            for j in range(chnls):
+                self._base_objs.append(Particle2_base(wrap(self._base_players,i), j, wrap(mul,i), wrap(add,i)))
+        self.play()
+
+    def setTable(self, x):
+        """
+        Replace the `table` attribute.
+
+        :Args:
+
+            x: PyoTableObject
+                new `table` attribute.
+
+        """
+        pyoArgsAssert(self, "t", x)
+        self._table = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setTable(wrap(x,i)) for i, obj in enumerate(self._base_players)]
+
+    def setEnv(self, x):
+        """
+        Replace the `env` attribute.
+
+        :Args:
+
+            x: PyoTableObject
+                new `env` attribute.
+
+        """
+        pyoArgsAssert(self, "t", x)
+        self._env = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setEnv(wrap(x,i)) for i, obj in enumerate(self._base_players)]
+
+    def setDens(self, x):
+        """
+        Replace the `dens` attribute.
+
+        :Args:
+
+            x: float or PyoObject
+                new `dens` attribute.
+
+        """
+        pyoArgsAssert(self, "O", x)
+        self._dens = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setDens(wrap(x,i)) for i, obj in enumerate(self._base_players)]
+
+    def setPitch(self, x):
+        """
+        Replace the `pitch` attribute.
+
+        :Args:
+
+            x: float or PyoObject
+                new `pitch` attribute.
+
+        """
+        pyoArgsAssert(self, "O", x)
+        self._pitch = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setPitch(wrap(x,i)) for i, obj in enumerate(self._base_players)]
+
+    def setPos(self, x):
+        """
+        Replace the `pos` attribute.
+
+        :Args:
+
+            x: float or PyoObject
+                new `pos` attribute.
+
+        """
+        pyoArgsAssert(self, "O", x)
+        self._pos = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setPos(wrap(x,i)) for i, obj in enumerate(self._base_players)]
+
+    def setDur(self, x):
+        """
+        Replace the `dur` attribute.
+
+        :Args:
+
+            x: float or PyoObject
+                new `dur` attribute.
+
+        """
+        pyoArgsAssert(self, "O", x)
+        self._dur = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setDur(wrap(x,i)) for i, obj in enumerate(self._base_players)]
+
+    def setDev(self, x):
+        """
+        Replace the `dev` attribute.
+
+        :Args:
+
+            x: float or PyoObject
+                new `dev` attribute.
+
+        """
+        pyoArgsAssert(self, "O", x)
+        self._dev = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setDev(wrap(x,i)) for i, obj in enumerate(self._base_players)]
+
+    def setPan(self, x):
+        """
+        Replace the `pan` attribute.
+
+        :Args:
+
+            x: float or PyoObject
+                new `pan` attribute.
+
+        """
+        pyoArgsAssert(self, "O", x)
+        self._pan = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setPan(wrap(x,i)) for i, obj in enumerate(self._base_players)]
+
+    def setFilterfreq(self, x):
+        """
+        Replace the `filterfreq` attribute.
+
+        :Args:
+
+            x: float or PyoObject
+                new `filterfreq` attribute.
+
+        """
+        pyoArgsAssert(self, "O", x)
+        self._filterfreq = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setFilterfreq(wrap(x,i)) for i, obj in enumerate(self._base_players)]
+
+    def setFilterq(self, x):
+        """
+        Replace the `filterq` attribute.
+
+        :Args:
+
+            x: float or PyoObject
+                new `filterq` attribute.
+
+        """
+        pyoArgsAssert(self, "O", x)
+        self._filterq = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setFilterq(wrap(x,i)) for i, obj in enumerate(self._base_players)]
+
+    def setFiltertype(self, x):
+        """
+        Replace the `filtertype` attribute.
+
+        :Args:
+
+            x: float or PyoObject
+                new `filtertype` attribute.
+
+        """
+        pyoArgsAssert(self, "O", x)
+        self._filtertype = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setFiltertype(wrap(x,i)) for i, obj in enumerate(self._base_players)]
+
+    def ctrl(self, map_list=None, title=None, wxnoserver=False):
+        tablesize = self._table.getSize(False)
+        self._map_list = [SLMap(1, 250, 'lin', 'dens', self._dens),
+                          SLMap(0.25, 2., 'lin', 'pitch', self._pitch),
+                          SLMap(0, tablesize, 'lin', 'pos', self._pos, res="int"),
+                          SLMap(0.001, 1., 'lin', 'dur', self._dur),
+                          SLMap(0., 1., 'lin', 'dev', self._dev),
+                          SLMap(0., 1., 'lin', 'pan', self._pan),
+                          SLMap(50., 18000., 'log', 'filterfreq', self._filterfreq),
+                          SLMap(0.25, 100., 'log', 'filterq', self._filterq),
+                          SLMap(0, 4., 'lin', 'filtertype', self._filtertype, res="int"),
+                          SLMapMul(self._mul)]
+        PyoObject.ctrl(self, map_list, title, wxnoserver)
+
+    @property
+    def table(self):
+        """PyoTableObject. Table containing the waveform samples."""
+        return self._table
+    @table.setter
+    def table(self, x): self.setTable(x)
+
+    @property
+    def env(self):
+        """PyoTableObject. Table containing the grain envelope."""
+        return self._env
+    @env.setter
+    def env(self, x): self.setEnv(x)
+
+    @property
+    def dens(self):
+        """float or PyoObject. Density of grains per second."""
+        return self._dens
+    @dens.setter
+    def dens(self, x): self.setDens(x)
+
+    @property
+    def pitch(self):
+        """float or PyoObject. Transposition factor of the grain."""
+        return self._pitch
+    @pitch.setter
+    def pitch(self, x): self.setPitch(x)
+
+    @property
+    def pos(self):
+        """float or PyoObject. Position of the pointer in the sound table."""
+        return self._pos
+    @pos.setter
+    def pos(self, x): self.setPos(x)
+
+    @property
+    def dur(self):
+        """float or PyoObject. Duration, in seconds, of the grain."""
+        return self._dur
+    @dur.setter
+    def dur(self, x): self.setDur(x)
+
+    @property
+    def dev(self):
+        """float or PyoObject. Deviation of the starting point of the grain in the table."""
+        return self._dev
+    @dev.setter
+    def dev(self, x): self.setDev(x)
+
+    @property
+    def pan(self):
+        """float or PyoObject.Panning of the grain."""
+        return self._pan
+    @pan.setter
+    def pan(self, x): self.setPan(x)
+
+    @property
+    def filterfreq(self):
+        """float or PyoObject.Grain's filter center/cutoff frequency."""
+        return self._filterfreq
+    @filterfreq.setter
+    def filterfreq(self, x): self.setFilterfreq(x)
+
+    @property
+    def filterq(self):
+        """float or PyoObject.Grain's filter Q."""
+        return self._filterq
+    @filterq.setter
+    def filterq(self, x): self.setFilterq(x)
+
+    @property
+    def filtertype(self):
+        """float or PyoObject.Grain's filter type."""
+        return self._filtertype
+    @filtertype.setter
+    def filtertype(self, x): self.setFiltertype(x)
+
+class TableScan(PyoObject):
+    """
+    Reads the content of a table in loop, without interpolation.
+
+    A simple table reader, sample by sample, with wrap-around when
+    reaching the end of the table.
+
+    :Parent: :py:class:`PyoObject`
+
+    :Args:
+
+        table: PyoTableObject
+            Table containing the waveform samples.
+
+    .. seealso::
+
+        :py:class:`Osc`, :py:class:`TableRead`
+
+    >>> s = Server().boot()
+    >>> s.start()
+    >>> tab = DataTable(s.getBufferSize(), 2)
+    >>> sig = Sine([500, 600], mul=0.3)
+    >>> fill = TableFill(sig, tab)
+    >>> scan = TableScan(tab).out()
+
+    """
+    def __init__(self, table, mul=1, add=0):
+        pyoArgsAssert(self, "tOO", table, mul, add)
+        PyoObject.__init__(self, mul, add)
+        self._table = table
+        table, mul, add, lmax = convertArgsToLists(table, mul, add)
+        self._base_objs = [TableScan_base(wrap(table,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
+
+    def setTable(self, x):
+        """
+        Replace the `table` attribute.
+
+        :Args:
+
+            x: PyoTableObject
+                new `table` attribute.
+
+        """
+        pyoArgsAssert(self, "t", x)
+        self._table = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setTable(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+
+    def reset(self):
+        """
+        Resets current phase to 0.
+
+        """
+        [obj.reset() for i, obj in enumerate(self._base_objs)]
+
+    @property
+    def table(self):
+        """PyoTableObject. Table containing the waveform samples."""
+        return self._table
+    @table.setter
+    def table(self, x): self.setTable(x)
diff --git a/pyolib/tables.py b/pyolib/tables.py
index 190786a..6e223f6 100644
--- a/pyolib/tables.py
+++ b/pyolib/tables.py
@@ -2338,7 +2338,7 @@ class PadSynthTable(PyoTableObject):
 
     http://zynaddsubfx.sourceforge.net/doc/PADsynth/PADsynth.htm
 
-    This algorithm generates some large wavetables that can played at
+    This algorithm generates some large wavetables that can be played at
     different speeds to get the desired sound. This algorithm describes
     only how these wavetables are generated. The result is a perfectly
     looped wavetable.
@@ -2352,7 +2352,7 @@ class PadSynthTable(PyoTableObject):
     :Args:
 
         basefreq: float, optional
-            The base frequencyof the algorithm in Hz. If the spreading factor
+            The base frequency of the algorithm in Hz. If the spreading factor
             is near 1.0, this frequency is the fundamental of the spectrum.
             Defaults to 440.
         spread: float, optional
@@ -2571,3 +2571,73 @@ class PadSynthTable(PyoTableObject):
         return self._damp
     @damp.setter
     def damp(self, x): self.setDamp(x)
+
+class SharedTable(PyoTableObject):
+    """
+    Create an inter-process shared memory table.
+
+    This table uses the given name to open an internal shared memory
+    object, used as the data memory of the table. Two or more tables
+    from different processes, if they use the same name, can read and
+    write to the same memory space.
+
+    .. note::
+
+        SharedTable is not implemented yet for Windows (unix only).
+
+    :Parent: :py:class:`PyoTableObject`
+
+    :Args:
+
+        name: string
+            Unique name in the system shared memory. Two or more tables created
+            with the same name will shared the same memory space. The name
+            must conform to the construction rules for a unix pathname (ie.
+            it must begin with a slash). Available at initialization time only.
+        create: loolean
+            If True, an entry will be create in the system shared memory.
+            If False, the object will use an already created shared memory.
+            Can't be a list. Available at initialization time only.
+        size: int
+            Size of the table in samples. Can't be a list.
+            Available at initialization time only.
+
+    >>> s = Server().boot()
+    >>> s.start()
+    >>> # Creating parent table.
+    >>> table = SharedTable(["/sharedl", "/sharedr"], True, s.getBufferSize())
+    >>> # Creating child table.
+    >>> shared = SharedTable(["/sharedl", "/sharedr"], False, s.getBufferSize())
+    >>> # Read and output the content of the parent table.
+    >>> tabread = TableRead(table, table.getRate(), True).out()
+    >>> # Record some signal signal in the child table.
+    >>> lfo = Sine(freq=[0.2, 0.25]).range(98, 102)
+    >>> wave = LFO(freq=lfo, type=4, sharp=0.7, mul=0.3)
+    >>> pos = Phasor(shared.getRate())
+    >>> record = TableWrite(wave, pos, shared)
+
+    """
+    def __init__(self, name, create, size):
+        if sys.platform == "win32":
+            raise Exception("SharedTable is not implemented yet for Windows.")
+        pyoArgsAssert(self, "sBI", name, create, size)
+        PyoTableObject.__init__(self, size)
+        self._name = name
+        self._create = create
+        name, lmax = convertArgsToLists(name)
+        self._base_objs = [SharedTable_base(wrap(name,i), create, size) for i in range(lmax)]
+
+    def getRate(self):
+        """
+        Returns the frequency (cycle per second) to give to an
+        oscillator to read the sound at its original pitch.
+
+        """
+        return self._base_objs[0].getRate()
+
+    @property
+    def size(self):
+        """int. Length of the table in samples."""
+        return self._size
+    @size.setter
+    def size(self, x): print("SharedTable 'size' attribute is read-only.")
diff --git a/pyolib/triggers.py b/pyolib/triggers.py
index b366178..438252b 100644
--- a/pyolib/triggers.py
+++ b/pyolib/triggers.py
@@ -61,6 +61,7 @@ class Trig(PyoObject):
     def __init__(self):
         PyoObject.__init__(self)
         self._base_objs = [Trig_base()]
+        self.play()
 
     def out(self, chnl=0, inc=1, dur=0, delay=0):
         return self.play(dur, delay)
@@ -177,13 +178,16 @@ class Seq(PyoObject):
 
         time: float or PyoObject, optional
             Base time between each trigger in seconds. Defaults to 1.
-        seq: list of ints, optional
+        seq: list of floats, optional
             Sequence of beat durations in time's unit. Defaults to [1].
         poly: int, optional
             Seq polyphony. Denotes how many independent streams are
             generated by the metronome, allowing overlapping processes.
 
             Available only at initialization. Defaults to 1.
+        onlyonce: boolean, optional
+            If True, the sequence will play only once and automatically stop.
+            Defaults to False.
 
     .. note::
 
@@ -200,19 +204,20 @@ class Seq(PyoObject):
     >>> a = SineLoop(tr, feedback=0.07, mul=amp).out()
 
     """
-    def __init__(self, time=1, seq=[1], poly=1):
-        pyoArgsAssert(self, "OlI", time, seq, poly)
+    def __init__(self, time=1, seq=[1], poly=1, onlyonce=False):
+        pyoArgsAssert(self, "OlIB", time, seq, poly)
         PyoObject.__init__(self)
         self._time = time
         self._seq = seq
         self._poly = poly
+        self._onlyonce = onlyonce
         time, lmax = convertArgsToLists(time)
         if type(seq[0]) != list:
-            self._base_players = [Seqer_base(wrap(time,i), seq, poly) for i in range(lmax)]
+            self._base_players = [Seqer_base(wrap(time,i), seq, poly, onlyonce) for i in range(lmax)]
         else:
             seqlen = len(seq)
             lmax = max(seqlen, lmax)
-            self._base_players = [Seqer_base(wrap(time,i), wrap(seq,i), poly) for i in range(lmax)]
+            self._base_players = [Seqer_base(wrap(time,i), wrap(seq,i), poly, onlyonce) for i in range(lmax)]
         self._base_objs = [Seq_base(wrap(self._base_players,j), i) for i in range(poly) for j in range(lmax)]
 
     def setTime(self, x):
@@ -236,7 +241,7 @@ class Seq(PyoObject):
 
         :Args:
 
-            x: list of ints
+            x: list of floats
                 New `seq` attribute.
 
         """
@@ -247,6 +252,20 @@ class Seq(PyoObject):
         else:
             [obj.setSeq(wrap(x,i)) for i, obj in enumerate(self._base_players)]
 
+    def setOnlyonce(self, x):
+        """
+        Replace the `onlyonce` attribute.
+
+        :Args:
+
+            x: boolean
+                New `onlyonce` attribute.
+
+        """
+        pyoArgsAssert(self, "B", x)
+        self._onlyonce = x
+        [obj.setOnlyonce(x) for obj in self._base_players]
+
     def out(self, chnl=0, inc=1, dur=0, delay=0):
         return self.play(dur, delay)
 
@@ -275,11 +294,18 @@ class Seq(PyoObject):
 
     @property
     def seq(self):
-        """List of ints. Sequence of beat durations in time's unit."""
+        """List of floats. Sequence of beat durations in time's unit."""
         return self._seq
     @seq.setter
     def seq(self, x): self.setSeq(x)
 
+    @property
+    def onlyonce(self):
+        """boolean. Trigger the sequence only once."""
+        return self._onlyonce
+    @onlyonce.setter
+    def onlyonce(self, x): self.setOnlyonce(x)
+
 class Cloud(PyoObject):
     """
     Generates random triggers.
@@ -408,6 +434,9 @@ class Beat(PyoObject):
             generated by the object, allowing overlapping processes.
 
             Available only at initialization. Defaults to 1.
+        onlyonce: boolean, optional
+            If True, the sequence will play only once and automatically stop.
+            Defaults to False.
 
     .. note::
 
@@ -434,8 +463,8 @@ class Beat(PyoObject):
     >>> a = Sine(freq=trhz, mul=tr2*0.3).out()
 
     """
-    def __init__(self, time=.125, taps=16, w1=80, w2=50, w3=30, poly=1):
-        pyoArgsAssert(self, "OinnnI", time, taps, w1, w2, w3, poly)
+    def __init__(self, time=.125, taps=16, w1=80, w2=50, w3=30, poly=1, onlyonce=False):
+        pyoArgsAssert(self, "OinnnIB", time, taps, w1, w2, w3, poly, onlyonce)
         PyoObject.__init__(self)
         self._tap_dummy = []
         self._amp_dummy = []
@@ -447,8 +476,9 @@ class Beat(PyoObject):
         self._w2 = w2
         self._w3 = w3
         self._poly = poly
+        self._onlyonce = onlyonce
         time, taps, w1, w2, w3, lmax = convertArgsToLists(time, taps, w1, w2, w3)
-        self._base_players = [Beater_base(wrap(time,i), wrap(taps,i), wrap(w1,i), wrap(w2,i), wrap(w3,i), poly) for i in range(lmax)]
+        self._base_players = [Beater_base(wrap(time,i), wrap(taps,i), wrap(w1,i), wrap(w2,i), wrap(w3,i), poly, onlyonce) for i in range(lmax)]
         self._base_objs = [Beat_base(wrap(self._base_players,j), i) for i in range(poly) for j in range(lmax)]
         self._tap_objs = [BeatTapStream_base(wrap(self._base_players,j), i) for i in range(poly) for j in range(lmax)]
         self._amp_objs = [BeatAmpStream_base(wrap(self._base_players,j), i) for i in range(poly) for j in range(lmax)]
@@ -509,12 +539,19 @@ class Beat(PyoObject):
         """
         [obj.reset() for obj in self._base_players]
 
-    def new(self):
+    def new(self, now=False):
         """
         Generates a new pattern with the current parameters.
 
+        :Args:
+
+            now: boolean
+                If True, the new sequence is immediately generated,
+                otherwise (the default), the new sequence is generated
+                after the current sequence is completed.
+
         """
-        [obj.new() for i, obj in enumerate(self._base_players)]
+        [obj.new(now) for i, obj in enumerate(self._base_players)]
 
     def fill(self):
         """
@@ -666,6 +703,20 @@ class Beat(PyoObject):
         w1, w2, w3, lmax = convertArgsToLists(w1, w2, w3)
         [obj.setWeights(wrap(w1,i), wrap(w2,i), wrap(w3,i)) for i, obj in enumerate(self._base_players)]
 
+    def setOnlyonce(self, x):
+        """
+        Replace the `onlyonce` attribute.
+
+        :Args:
+
+            x: boolean
+                New `onlyonce` attribute.
+
+        """
+        pyoArgsAssert(self, "B", x)
+        self._onlyonce = x
+        [obj.setOnlyonce(x) for obj in self._base_players]
+
     def play(self, dur=0, delay=0):
         dur, delay, lmax = convertArgsToLists(dur, delay)
         self._tap_objs = [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._tap_objs)]
@@ -739,6 +790,13 @@ class Beat(PyoObject):
     @w3.setter
     def w3(self, x): self.setW3(x)
 
+    @property
+    def onlyonce(self):
+        """boolean. Trigger the sequence only once."""
+        return self._onlyonce
+    @onlyonce.setter
+    def onlyonce(self, x): self.setOnlyonce(x)
+
 class TrigRandInt(PyoObject):
     """
     Pseudo-random integer generator.
@@ -778,6 +836,7 @@ class TrigRandInt(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, max, mul, add, lmax = convertArgsToLists(self._in_fader, max, mul, add)
         self._base_objs = [TrigRandInt_base(wrap(in_fader,i), wrap(max,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -876,6 +935,7 @@ class TrigRand(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, min, max, port, init, mul, add, lmax = convertArgsToLists(self._in_fader, min, max, port, init, mul, add)
         self._base_objs = [TrigRand_base(wrap(in_fader,i), wrap(min,i), wrap(max,i), wrap(port,i), wrap(init,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -1018,6 +1078,7 @@ class TrigChoice(PyoObject):
             choicelen = len(choice)
             lmax = max(choicelen, lmax)
             self._base_objs = [TrigChoice_base(wrap(in_fader,i), wrap(choice,i), wrap(port,i), wrap(init,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -1140,6 +1201,7 @@ class TrigFunc(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, function, arg, lmax = convertArgsToLists(self._in_fader, function, arg)
         self._base_objs = [TrigFunc_base(wrap(in_fader,i), WeakMethod(wrap(function,i)), wrap(arg,i)) for i in range(lmax)]
+        self.play()
 
     def out(self, chnl=0, inc=1, dur=0, delay=0):
         return self.play(dur, delay)
@@ -1267,6 +1329,7 @@ class TrigEnv(PyoObject):
         in_fader, table, dur, interp, mul, add, lmax = convertArgsToLists(self._in_fader, table, dur, interp, mul, add)
         self._base_objs = [TrigEnv_base(wrap(in_fader,i), wrap(table,i), wrap(dur,i), wrap(interp,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
         self._trig_objs = Dummy([TriggerDummy_base(obj) for obj in self._base_objs])
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -1406,6 +1469,7 @@ class TrigLinseg(PyoObject):
         in_fader, mul, add, lmax = convertArgsToLists(self._in_fader, mul, add)
         self._base_objs = [TrigLinseg_base(wrap(in_fader,i), list, wrap(mul,i), wrap(add,i)) for i in range(lmax)]
         self._trig_objs = Dummy([TriggerDummy_base(obj) for obj in self._base_objs])
+        self.play()
 
     def out(self, chnl=0, inc=1, dur=0, delay=0):
         return self.play(dur, delay)
@@ -1570,6 +1634,7 @@ class TrigExpseg(PyoObject):
         in_fader, exp, inverse, mul, add, lmax = convertArgsToLists(self._in_fader, exp, inverse, mul, add)
         self._base_objs = [TrigExpseg_base(wrap(in_fader,i), list, wrap(exp,i), wrap(inverse,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
         self._trig_objs = Dummy([TriggerDummy_base(obj) for obj in self._base_objs])
+        self.play()
 
     def out(self, chnl=0, inc=1, dur=0, delay=0):
         return self.play(dur, delay)
@@ -1830,6 +1895,7 @@ class TrigXnoise(PyoObject):
         for i, t in enumerate(dist):
             if type(t) in [bytes_t, unicode_t]: dist[i] = XNOISE_DICT.get(t, 0)
         self._base_objs = [TrigXnoise_base(wrap(in_fader,i), wrap(dist,i), wrap(x1,i), wrap(x2,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -2046,6 +2112,7 @@ class TrigXnoiseMidi(PyoObject):
         for i, t in enumerate(dist):
             if type(t) in [bytes_t, unicode_t]: dist[i] = XNOISE_DICT.get(t, 0)
         self._base_objs = [TrigXnoiseMidi_base(wrap(in_fader,i), wrap(dist,i), wrap(x1,i), wrap(x2,i), wrap(scale,i), wrap(mrange,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -2241,6 +2308,7 @@ class Counter(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, min, max, dir, mul, add, lmax = convertArgsToLists(self._in_fader, min, max, dir, mul, add)
         self._base_objs = [Counter_base(wrap(in_fader,i), wrap(min,i), wrap(max,i), wrap(dir,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def out(self, chnl=0, inc=1, dur=0, delay=0):
         return self.play(dur, delay)
@@ -2404,6 +2472,7 @@ class Select(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, value, mul, add, lmax = convertArgsToLists(self._in_fader, value, mul, add)
         self._base_objs = [Select_base(wrap(in_fader,i), wrap(value,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def out(self, chnl=0, inc=1, dur=0, delay=0):
         return self.play(dur, delay)
@@ -2490,6 +2559,7 @@ class Change(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, mul, add, lmax = convertArgsToLists(self._in_fader, mul, add)
         self._base_objs = [Change_base(wrap(in_fader,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def out(self, chnl=0, inc=1, dur=0, delay=0):
         return self.play(dur, delay)
@@ -2570,6 +2640,7 @@ class Thresh(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, threshold, dir, mul, add, lmax = convertArgsToLists(self._in_fader, threshold, dir, mul, add)
         self._base_objs = [Thresh_base(wrap(in_fader,i), wrap(threshold,i), wrap(dir,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def out(self, chnl=0, inc=1, dur=0, delay=0):
         return self.play(dur, delay)
@@ -2683,6 +2754,7 @@ class Percent(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, percent, mul, add, lmax = convertArgsToLists(self._in_fader, percent, mul, add)
         self._base_objs = [Percent_base(wrap(in_fader,i), wrap(percent,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def out(self, chnl=0, inc=1, dur=0, delay=0):
         return self.play(dur, delay)
@@ -2780,6 +2852,7 @@ class Timer(PyoObject):
         self._in_fader2 = InputFader(input2)
         in_fader, in_fader2, mul, add, lmax = convertArgsToLists(self._in_fader, self._in_fader2, mul, add)
         self._base_objs = [Timer_base(wrap(in_fader,i), wrap(in_fader2,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -2882,6 +2955,7 @@ class Iter(PyoObject):
             lmax = max(choicelen, lmax)
             self._base_objs = [Iter_base(wrap(in_fader,i), wrap(x,i), wrap(init,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
         self._trig_objs = Dummy([TriggerDummy_base(obj) for obj in self._base_objs])
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -3012,6 +3086,7 @@ class Count(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, min, max, mul, add, lmax = convertArgsToLists(self._in_fader, min, max, mul, add)
         self._base_objs = [Count_base(wrap(in_fader,i), wrap(min,i), wrap(max,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -3127,6 +3202,7 @@ class NextTrig(PyoObject):
         self._in_fader2 = InputFader(input2)
         in_fader, in_fader2, mul, add, lmax = convertArgsToLists(self._in_fader, self._in_fader2, mul, add)
         self._base_objs = [NextTrig_base(wrap(in_fader,i), wrap(in_fader2,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -3216,6 +3292,7 @@ class TrigVal(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, value, init, mul, add, lmax = convertArgsToLists(self._in_fader, value, init, mul, add)
         self._base_objs = [TrigVal_base(wrap(in_fader,i), wrap(value,i), wrap(init,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -3610,6 +3687,7 @@ class TrigBurst(PyoObject):
         self._amp_objs = [TrigBurstAmpStream_base(wrap(self._base_players,j), i) for i in range(poly) for j in range(lmax)]
         self._dur_objs = [TrigBurstDurStream_base(wrap(self._base_players,j), i) for i in range(poly) for j in range(lmax)]
         self._end_objs = [TrigBurstEndStream_base(wrap(self._base_players,j), i) for i in range(poly) for j in range(lmax)]
+        self.play()
 
     def __getitem__(self, i):
         if i == 'tap':
diff --git a/pyolib/utils.py b/pyolib/utils.py
index 0e8b27d..c1abb5f 100644
--- a/pyolib/utils.py
+++ b/pyolib/utils.py
@@ -108,6 +108,7 @@ class Print(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, method, interval, message, lmax = convertArgsToLists(self._in_fader, method, interval, message)
         self._base_objs = [Print_base(wrap(in_fader,i), wrap(method,i), wrap(interval,i), wrap(message,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -255,6 +256,7 @@ class Snap(PyoObject):
             choicelen = len(choice)
             lmax = max(choicelen, lmax)
             self._base_objs = [Snap_base(wrap(in_fader,i), wrap(choice,i), wrap(scale,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -362,6 +364,7 @@ class Interp(PyoObject):
         self._in_fader2 = InputFader(input2)
         in_fader, in_fader2, interp, mul, add, lmax = convertArgsToLists(self._in_fader, self._in_fader2, interp, mul, add)
         self._base_objs = [Interp_base(wrap(in_fader,i), wrap(in_fader2,i), wrap(interp,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -472,6 +475,7 @@ class SampHold(PyoObject):
         self._in_fader2 = InputFader(controlsig)
         in_fader, in_fader2, value, mul, add, lmax = convertArgsToLists(self._in_fader, self._in_fader2, value, mul, add)
         self._base_objs = [SampHold_base(wrap(in_fader,i), wrap(in_fader2,i), wrap(value,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -634,6 +638,7 @@ class Record(PyoObject):
         else:
             print('Warning: Filename has no extension. Using fileformat value.')
         self._base_objs = [Record_base(self._in_fader.getBaseObjects(), filename, chnls, fileformat, sampletype, buffering, quality)]
+        self.play()
 
     def out(self, chnl=0, inc=1, dur=0, delay=0):
         return self.play(dur, delay)
@@ -691,6 +696,7 @@ class Denorm(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, mul, add, lmax = convertArgsToLists(self._in_fader, mul, add)
         self._base_objs = [Denorm_base(wrap(in_fader,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -880,6 +886,7 @@ class ControlRead(PyoObject):
             f.close()
             self._base_objs.append(ControlRead_base(values, rate, loop, interp, wrap(mul,i), wrap(add,i)))
         self._trig_objs = Dummy([TriggerDummy_base(obj) for obj in self._base_objs])
+        self.play()
 
     def out(self, chnl=0, inc=1, dur=0, delay=0):
         return self.play(dur, delay)
@@ -1098,6 +1105,7 @@ class NoteinRead(PyoObject):
             self._base_objs.append(NoteinRead_base(amps, timestamps, loop, wrap(mul,i), wrap(add,i)))
             _trig_objs_tmp.append(TriggerDummy_base(self._base_objs[-1]))
         self._trig_objs = Dummy(_trig_objs_tmp)
+        self.play()
 
     def __getitem__(self, str):
         if str == 'trig':
@@ -1192,6 +1200,7 @@ class DBToA(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, mul, add, lmax = convertArgsToLists(self._in_fader, mul, add)
         self._base_objs = [DBToA_base(wrap(in_fader,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -1248,6 +1257,7 @@ class AToDB(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, mul, add, lmax = convertArgsToLists(self._in_fader, mul, add)
         self._base_objs = [AToDB_base(wrap(in_fader,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -1320,6 +1330,7 @@ class Scale(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, inmin, inmax, outmin, outmax, exp, mul, add, lmax = convertArgsToLists(self._in_fader, inmin, inmax, outmin, outmax, exp, mul, add)
         self._base_objs = [Scale_base(wrap(in_fader,i), wrap(inmin,i), wrap(inmax,i), wrap(outmin,i), wrap(outmax,i), wrap(exp,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -1492,6 +1503,7 @@ class CentsToTranspo(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, mul, add, lmax = convertArgsToLists(self._in_fader, mul, add)
         self._base_objs = [CentsToTranspo_base(wrap(in_fader,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -1546,6 +1558,7 @@ class TranspoToCents(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, mul, add, lmax = convertArgsToLists(self._in_fader, mul, add)
         self._base_objs = [TranspoToCents_base(wrap(in_fader,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -1600,6 +1613,7 @@ class MToF(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, mul, add, lmax = convertArgsToLists(self._in_fader, mul, add)
         self._base_objs = [MToF_base(wrap(in_fader,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -1657,6 +1671,7 @@ class FToM(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, mul, add, lmax = convertArgsToLists(self._in_fader, mul, add)
         self._base_objs = [FToM_base(wrap(in_fader,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -1718,6 +1733,7 @@ class MToT(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, centralkey, mul, add, lmax = convertArgsToLists(self._in_fader, centralkey, mul, add)
         self._base_objs = [MToT_base(wrap(in_fader,i), wrap(centralkey,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -1798,6 +1814,7 @@ class Between(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, min, max, mul, add, lmax = convertArgsToLists(self._in_fader, min, max, mul, add)
         self._base_objs = [Between_base(wrap(in_fader,i), wrap(min,i), wrap(max,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -1909,6 +1926,7 @@ class TrackHold(PyoObject):
         self._in_fader2 = InputFader(controlsig)
         in_fader, in_fader2, value, mul, add, lmax = convertArgsToLists(self._in_fader, self._in_fader2, value, mul, add)
         self._base_objs = [TrackHold_base(wrap(in_fader,i), wrap(in_fader2,i), wrap(value,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -2037,3 +2055,4 @@ class Resample(PyoObject):
         self._mode = mode
         _input, mode, mul, add, lmax = convertArgsToLists(input, mode, mul, add)
         self._base_objs = [Resample_base(wrap(_input,i), wrap(mode,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        self.play()
diff --git a/scripts/release_doc_src.sh b/scripts/release_doc_src.sh
index 103c3bd..f908f09 100755
--- a/scripts/release_doc_src.sh
+++ b/scripts/release_doc_src.sh
@@ -6,7 +6,7 @@
 # 3. Execute from pyo folder : ./scripts/release_doc_src.sh
 #
 
-version=0.8.1
+version=0.8.3
 replace=XXX
 
 doc_rep=pyo_XXX-doc
diff --git a/setup.py b/setup.py
index 664cb53..8bf6a36 100644
--- a/setup.py
+++ b/setup.py
@@ -22,7 +22,7 @@ from distutils.sysconfig import get_python_lib
 from distutils.core import setup, Extension
 import os, sys, py_compile
 
-pyo_version = "0.8.1"
+pyo_version = "0.8.3"
 build_with_jack_support = False
 compile_externals = False
 
diff --git a/src/engine/ad_jack.c b/src/engine/ad_jack.c
index 1e8996e..69e7734 100644
--- a/src/engine/ad_jack.c
+++ b/src/engine/ad_jack.c
@@ -25,12 +25,11 @@ int
 jack_callback(jack_nframes_t nframes, void *arg) {
     int i, j;
     Server *server = (Server *) arg;
+
     assert(nframes == server->bufferSize);
+
     jack_default_audio_sample_t *in_buffers[server->ichnls], *out_buffers[server->nchnls];
 
-    if (server->withPortMidi == 1) {
-        pyoGetMidiEvents(server);
-    }
     PyoJackBackendData *be_data = (PyoJackBackendData *) server->audio_be_data;
     for (i = 0; i < server->ichnls; i++) {
         in_buffers[i] = jack_port_get_buffer(be_data->jack_in_ports[i+server->input_offset], server->bufferSize);
@@ -39,6 +38,21 @@ jack_callback(jack_nframes_t nframes, void *arg) {
         out_buffers[i] = jack_port_get_buffer(be_data->jack_out_ports[i+server->output_offset], server->bufferSize);
 
     }
+
+    /* Outputs zeros while the audio server is not started. */
+    if (!server->server_started) {
+        for (i=0; i<server->bufferSize; i++) {
+            for (j=0; j<server->nchnls; j++) {
+                out_buffers[j][i] = 0.0;
+            }
+        }
+        return 0;
+    }
+
+    if (server->withPortMidi == 1) {
+        pyoGetMidiEvents(server);
+    }
+
     /* jack audio data is not interleaved */
     if (server->duplex == 1) {
         for (i=0; i<server->bufferSize; i++) {
@@ -81,7 +95,7 @@ jack_error_cb(const char *desc) {
 void
 jack_shutdown_cb(void *arg) {
     Server *s = (Server *) arg;
-    Server_shut_down(s);
+    Server_shutdown(s);
     Server_warning(s, "JACK server shutdown. Pyo Server shut down.\n");
 }
 
@@ -260,13 +274,27 @@ Server_jack_init(Server *self) {
     jack_set_sample_rate_callback(be_data->jack_client, jack_srate_cb, (void *) self);
     jack_on_shutdown(be_data->jack_client, jack_shutdown_cb, (void *) self);
     jack_set_buffer_size_callback(be_data->jack_client, jack_bufsize_cb, (void *) self);
+    jack_set_process_callback(be_data->jack_client, jack_callback, (void *) self);
+
+    if (jack_activate(be_data->jack_client)) {
+        Server_error(self, "Jack error: cannot activate jack client.\n");
+        //Server_shutdown(self);
+        return -1;
+    }
+
+    Server_jack_autoconnect(self);
+
     return 0;
 }
 
 int
 Server_jack_deinit(Server *self) {
+    int ret;
     PyoJackBackendData *be_data = (PyoJackBackendData *) self->audio_be_data;
-    int ret = jack_client_close(be_data->jack_client);
+    ret = jack_deactivate(be_data->jack_client);
+    if (ret)
+        Server_error(self, "Jack error: cannot deactivate jack client.\n");
+    ret = jack_client_close(be_data->jack_client);
     if (ret)
         Server_error(self, "Jack error: cannot close client.\n");
     free(be_data->jack_in_ports);
@@ -277,24 +305,10 @@ Server_jack_deinit(Server *self) {
 
 int
 Server_jack_start(Server *self) {
-    PyoJackBackendData *be_data = (PyoJackBackendData *) self->audio_be_data;
-    jack_set_process_callback(be_data->jack_client, jack_callback, (void *) self);
-    if (jack_activate(be_data->jack_client)) {
-        Server_error(self, "Jack error: cannot activate jack client.\n");
-        jack_client_close(be_data->jack_client);
-        Server_shut_down(self);
-        return -1;
-    }
-    Server_jack_autoconnect(self);
     return 0;
 }
 
 int
 Server_jack_stop(Server *self) {
-    PyoJackBackendData *be_data = (PyoJackBackendData *) self->audio_be_data;
-    int ret = jack_deactivate(be_data->jack_client);
-    if (ret)
-        Server_error(self, "Jack error: cannot deactivate jack client.\n");
-    self->server_started = 0;
-    return ret;
+    return 0;
 }
diff --git a/src/engine/ad_portaudio.c b/src/engine/ad_portaudio.c
index 20e714c..5e92703 100644
--- a/src/engine/ad_portaudio.c
+++ b/src/engine/ad_portaudio.c
@@ -198,7 +198,7 @@ Server_pa_init(Server *self)
     outputParameters.device = outDevice;
     outputParameters.channelCount = self->nchnls + self->output_offset;
     outputParameters.sampleFormat = sampleFormat;
-    outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultHighOutputLatency;
+    outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
     outputParameters.hostApiSpecificStreamInfo = NULL;
 
     if (self->duplex == 1) {
@@ -206,7 +206,7 @@ Server_pa_init(Server *self)
         inputParameters.device = inDevice;
         inputParameters.channelCount = self->ichnls + self->input_offset;
         inputParameters.sampleFormat = sampleFormat;
-        inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultHighInputLatency ;
+        inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;
         inputParameters.hostApiSpecificStreamInfo = NULL;
     }
 
diff --git a/src/engine/md_portmidi.c b/src/engine/md_portmidi.c
index 0c65f55..35a9d36 100644
--- a/src/engine/md_portmidi.c
+++ b/src/engine/md_portmidi.c
@@ -32,7 +32,7 @@ static PyoMidiEvent PmEventToPyoMidiEvent(PmEvent buffer)
 void portmidiGetEvents(Server *self)
 {
     int i;
-    PmError result;
+    PmError result, length;
     PmEvent buffer;
 
     PyoPmBackendData *be_data = (PyoPmBackendData *) self->midi_be_data;
@@ -41,9 +41,9 @@ void portmidiGetEvents(Server *self)
         do {
             result = Pm_Poll(be_data->midiin[i]);
             if (result) {
-                if (Pm_Read(be_data->midiin[i], &buffer, 1) == pmBufferOverflow)
-                    continue;
-                self->midiEvents[self->midi_count++] = PmEventToPyoMidiEvent(buffer);
+                length = Pm_Read(be_data->midiin[i], &buffer, 1);
+                if (length > 0)
+                    self->midiEvents[self->midi_count++] = PmEventToPyoMidiEvent(buffer);
             }
         } while (result);
     }
@@ -147,7 +147,7 @@ Server_pm_init(Server *self)
                 if (outinfo != NULL) {
                     if (outinfo->output) {
                         Pt_Start(1, 0, 0); /* start a timer with millisecond accuracy */
-                        pmerr = Pm_OpenOutput(&be_data->midiout[0], self->midi_output, NULL, 0, NULL, NULL, 1);
+                        pmerr = Pm_OpenOutput(&be_data->midiout[0], self->midi_output, NULL, 100, NULL, NULL, 1);
                         if (pmerr) {
                             Server_warning(self,
                                      "Portmidi warning: could not open midi output %d (%s): %s\n",
diff --git a/src/engine/midilistenermodule.c b/src/engine/midilistenermodule.c
index 7039c3b..6b1a3f1 100644
--- a/src/engine/midilistenermodule.c
+++ b/src/engine/midilistenermodule.c
@@ -30,9 +30,11 @@ typedef struct {
     PyObject_HEAD
     PyObject *midicallable;
     PmStream *midiin[64];
-    int mididev;
+    PyObject *mididev;
+    int ids[64];
     int midicount;
     int active;
+    int reportdevice;
 } MidiListener;
 
 void process_midi(PtTimestamp timestamp, void *userData)
@@ -55,11 +57,21 @@ void process_midi(PtTimestamp timestamp, void *userData)
                 status = Pm_MessageStatus(buffer.message);
                 data1 = Pm_MessageData1(buffer.message);
                 data2 = Pm_MessageData2(buffer.message);
-                tup = PyTuple_New(3);
-                PyTuple_SetItem(tup, 0, PyInt_FromLong(status));
-                PyTuple_SetItem(tup, 1, PyInt_FromLong(data1));
-                PyTuple_SetItem(tup, 2, PyInt_FromLong(data2));
-                PyObject_Call((PyObject *)server->midicallable, tup, NULL);
+                if (server->reportdevice) {
+                    tup = PyTuple_New(4);
+                    PyTuple_SetItem(tup, 0, PyInt_FromLong(status));
+                    PyTuple_SetItem(tup, 1, PyInt_FromLong(data1));
+                    PyTuple_SetItem(tup, 2, PyInt_FromLong(data2));
+                    PyTuple_SetItem(tup, 3, PyInt_FromLong(server->ids[i]));
+                    PyObject_Call((PyObject *)server->midicallable, tup, NULL);
+                }
+                else {
+                    tup = PyTuple_New(3);
+                    PyTuple_SetItem(tup, 0, PyInt_FromLong(status));
+                    PyTuple_SetItem(tup, 1, PyInt_FromLong(data1));
+                    PyTuple_SetItem(tup, 2, PyInt_FromLong(data2));
+                    PyObject_Call((PyObject *)server->midicallable, tup, NULL);
+                }
             }
         }
     } while (result);
@@ -72,6 +84,7 @@ static int
 MidiListener_traverse(MidiListener *self, visitproc visit, void *arg)
 {
     Py_VISIT(self->midicallable);
+    Py_VISIT(self->mididev);
     return 0;
 }
 
@@ -79,6 +92,7 @@ static int
 MidiListener_clear(MidiListener *self)
 {
     Py_CLEAR(self->midicallable);
+    Py_CLEAR(self->mididev);
     return 0;
 }
 
@@ -94,28 +108,33 @@ MidiListener_dealloc(MidiListener* self)
 static PyObject *
 MidiListener_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
-    PyObject *midicalltmp=NULL;
+    PyObject *midicalltmp=NULL, *mididevtmp=NULL;
     MidiListener *self;
 
     self = (MidiListener *)type->tp_alloc(type, 0);
 
-    self->active = self->midicount = 0;
-    self->mididev = -1;
+    self->active = self->midicount = self->reportdevice = 0;
 
-    static char *kwlist[] = {"midicallable", "mididevice", NULL};
+    static char *kwlist[] = {"midicallable", "mididevice", "reportdevice", NULL};
 
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "Oi", kwlist, &midicalltmp, &self->mididev))
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "OOi", kwlist, &midicalltmp, &mididevtmp, &self->reportdevice))
         Py_RETURN_NONE;
 
     if (midicalltmp) {
         PyObject_CallMethod((PyObject *)self, "setMidiFunction", "O", midicalltmp);
     }
 
+    if (mididevtmp) {
+        Py_INCREF(mididevtmp);
+        Py_XDECREF(self->mididev);
+        self->mididev = mididevtmp;
+    }
+
     return (PyObject *)self;
 }
 
 static PyObject * MidiListener_play(MidiListener *self) {
-    int i, num_devices;
+    int i, num_devices, lsize, mididev;
     PmError pmerr;
 
     /* always start the timer before you start midi */
@@ -126,28 +145,55 @@ static PyObject * MidiListener_play(MidiListener *self) {
         PySys_WriteStdout("Portmidi warning: could not initialize Portmidi: %s\n", Pm_GetErrorText(pmerr));
     }
 
+    lsize = PyList_Size(self->mididev);
+
     num_devices = Pm_CountDevices();
     if (num_devices > 0) {
-        if (self->mididev < num_devices) {
-            if (self->mididev == -1)
-                self->mididev = Pm_GetDefaultInputDeviceID();
-            const PmDeviceInfo *info = Pm_GetDeviceInfo(self->mididev);
-            if (info != NULL) {
-                if (info->input) {
-                    pmerr = Pm_OpenInput(&self->midiin[0], self->mididev, NULL, 100, NULL, NULL);
-                    if (pmerr) {
-                        PySys_WriteStdout("Portmidi warning: could not open midi input %d (%s): %s\n",
-                             self->mididev, info->name, Pm_GetErrorText(pmerr));
+        if (lsize == 1) {
+            mididev = PyLong_AsLong(PyList_GetItem(self->mididev, 0));
+            if (mididev < num_devices) {
+                if (mididev == -1)
+                    mididev = Pm_GetDefaultInputDeviceID();
+                const PmDeviceInfo *info = Pm_GetDeviceInfo(mididev);
+                if (info != NULL) {
+                    if (info->input) {
+                        pmerr = Pm_OpenInput(&self->midiin[0], mididev, NULL, 100, NULL, NULL);
+                        if (pmerr) {
+                            PySys_WriteStdout("Portmidi warning: could not open midi input %d (%s): %s\n",
+                                 mididev, info->name, Pm_GetErrorText(pmerr));
+                        }
+                        else {
+                            self->midicount = 1;
+                            self->ids[0] = mididev;
+                        }
                     }
-                    else {
-                        self->midicount = 1;
+                }
+            }
+            else if (mididev >= num_devices) {
+                self->midicount = 0;
+                for (i=0; i<num_devices; i++) {
+                    const PmDeviceInfo *info = Pm_GetDeviceInfo(i);
+                    if (info != NULL) {
+                        if (info->input) {
+                            pmerr = Pm_OpenInput(&self->midiin[self->midicount], i, NULL, 100, NULL, NULL);
+                            if (pmerr) {
+                                PySys_WriteStdout("Portmidi warning: could not open midi input %d (%s): %s\n",
+                                        i, info->name, Pm_GetErrorText(pmerr));
+                            }
+                            else {
+                                self->ids[self->midicount] = i;
+                                self->midicount++;
+                            }
+                        }
                     }
                 }
             }
         }
-        else if (self->mididev >= num_devices) {
+        else {
             self->midicount = 0;
             for (i=0; i<num_devices; i++) {
+                if (PySequence_Contains(self->mididev, PyLong_FromLong(i)) == 0)
+                    continue;
                 const PmDeviceInfo *info = Pm_GetDeviceInfo(i);
                 if (info != NULL) {
                     if (info->input) {
@@ -157,6 +203,7 @@ static PyObject * MidiListener_play(MidiListener *self) {
                                     i, info->name, Pm_GetErrorText(pmerr));
                         }
                         else {
+                            self->ids[self->midicount] = i;
                             self->midicount++;
                         }
                     }
@@ -208,6 +255,19 @@ MidiListener_setMidiFunction(MidiListener *self, PyObject *arg)
 	return Py_None;
 }
 
+PyObject *
+MidiListener_getDeviceInfos(MidiListener *self) {
+    int i;
+    PyObject *str;
+    PyObject *lst = PyList_New(0);
+    for (i = 0; i < self->midicount; i++) {
+        const PmDeviceInfo *info = Pm_GetDeviceInfo(self->ids[i]);
+        str = PyBytes_FromFormat("id: %d, name: %s, interface: %s\n", self->ids[i], info->name, info->interf);
+        PyList_Append(lst, str);
+    }
+    return lst;
+}
+
 static PyMemberDef MidiListener_members[] = {
     {NULL}  /* Sentinel */
 };
@@ -216,6 +276,7 @@ static PyMethodDef MidiListener_methods[] = {
     {"play", (PyCFunction)MidiListener_play, METH_NOARGS, "Starts computing without sending sound to soundcard."},
     {"stop", (PyCFunction)MidiListener_stop, METH_NOARGS, "Stops computing."},
     {"setMidiFunction", (PyCFunction)MidiListener_setMidiFunction, METH_O, "Sets the function to be called."},
+    {"getDeviceInfos", (PyCFunction)MidiListener_getDeviceInfos, METH_NOARGS, "Returns a list of device infos."},
     {NULL}  /* Sentinel */
 };
 
@@ -259,3 +320,253 @@ PyTypeObject MidiListenerType = {
     0,                         /* tp_alloc */
     MidiListener_new,                 /* tp_new */
 };
+
+typedef struct {
+    PyObject_HEAD
+    PmStream *midiout[64];
+    PyObject *mididev;
+    int ids[64];
+    int midicount;
+    int active;
+} MidiDispatcher;
+
+static int
+MidiDispatcher_traverse(MidiDispatcher *self, visitproc visit, void *arg) {
+    return 0;
+}
+
+static int
+MidiDispatcher_clear(MidiDispatcher *self) {
+    return 0;
+}
+
+static void
+MidiDispatcher_dealloc(MidiDispatcher* self) {
+    if (self->active == 1)
+        PyObject_CallMethod((PyObject *)self, "stop", NULL);
+    MidiDispatcher_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+MidiDispatcher_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    PyObject *mididevtmp=NULL;
+    MidiDispatcher *self;
+
+    self = (MidiDispatcher *)type->tp_alloc(type, 0);
+
+    self->active = self->midicount = 0;
+
+    static char *kwlist[] = {"mididevice", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &mididevtmp))
+        Py_RETURN_NONE;
+
+    if (mididevtmp) {
+        Py_INCREF(mididevtmp);
+        Py_XDECREF(self->mididev);
+        self->mididev = mididevtmp;
+    }
+
+    return (PyObject *)self;
+}
+
+static PyObject * MidiDispatcher_play(MidiDispatcher *self) {
+    int i, num_devices, lsize, mididev;
+    PmError pmerr;
+
+    /* always start the timer before you start midi */
+    Pt_Start(1, 0, 0);
+    
+    pmerr = Pm_Initialize();
+    if (pmerr) {
+        PySys_WriteStdout("Portmidi warning: could not initialize Portmidi: %s\n", Pm_GetErrorText(pmerr));
+    }
+
+    lsize = PyList_Size(self->mididev);
+
+    num_devices = Pm_CountDevices();
+    if (num_devices > 0) {
+        if (lsize == 1) {
+            mididev = PyLong_AsLong(PyList_GetItem(self->mididev, 0));
+            if (mididev < num_devices) {
+                if (mididev == -1)
+                    mididev = Pm_GetDefaultOutputDeviceID();
+                const PmDeviceInfo *info = Pm_GetDeviceInfo(mididev);
+                if (info != NULL) {
+                    if (info->output) {
+                        pmerr = Pm_OpenOutput(&self->midiout[0], mididev, NULL, 100, NULL, NULL, 1);
+                        if (pmerr) {
+                            PySys_WriteStdout("Portmidi warning: could not open midi output %d (%s): %s\n",
+                                 mididev, info->name, Pm_GetErrorText(pmerr));
+                        }
+                        else {
+                            self->midicount = 1;
+                            self->ids[0] = mididev;
+                        }
+                    }
+                }
+            }
+            else if (mididev >= num_devices) {
+                self->midicount = 0;
+                for (i=0; i<num_devices; i++) {
+                    const PmDeviceInfo *info = Pm_GetDeviceInfo(i);
+                    if (info != NULL) {
+                        if (info->output) {
+                            pmerr = Pm_OpenOutput(&self->midiout[self->midicount], i, NULL, 100, NULL, NULL, 1);
+                            if (pmerr) {
+                                PySys_WriteStdout("Portmidi warning: could not open midi output %d (%s): %s\n",
+                                        i, info->name, Pm_GetErrorText(pmerr));
+                            }
+                            else {
+                                self->ids[self->midicount] = i;
+                                self->midicount++;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        else {
+            self->midicount = 0;
+            for (i=0; i<num_devices; i++) {
+                if (PySequence_Contains(self->mididev, PyLong_FromLong(i)) == 0)
+                    continue;
+                const PmDeviceInfo *info = Pm_GetDeviceInfo(i);
+                if (info != NULL) {
+                    if (info->output) {
+                        pmerr = Pm_OpenOutput(&self->midiout[self->midicount], i, NULL, 100, NULL, NULL, 1);
+                        if (pmerr) {
+                            PySys_WriteStdout("Portmidi warning: could not open midi output %d (%s): %s\n",
+                                    i, info->name, Pm_GetErrorText(pmerr));
+                        }
+                        else {
+                            self->ids[self->midicount] = i;
+                            self->midicount++;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    if (self->midicount > 0)
+        self->active = 1;
+
+	Py_INCREF(Py_None);
+	return Py_None;
+};
+
+static PyObject * MidiDispatcher_stop(MidiDispatcher *self) { 
+    int i;
+    Pt_Stop();
+    for (i=0; i<self->midicount; i++) {
+        Pm_Close(self->midiout[i]);
+    }
+    Pm_Terminate();    
+    self->active = 0;
+	Py_INCREF(Py_None);
+	return Py_None;
+};
+
+PyObject *
+MidiDispatcher_send(MidiDispatcher *self, PyObject *args)
+{
+    int i, status, data1, data2, device, curtime;
+    PmTimestamp timestamp;
+    PmEvent buffer[1];
+
+    if (! PyArg_ParseTuple(args, "iiili", &status, &data1, &data2, &timestamp, &device))
+        return PyInt_FromLong(-1);
+
+    curtime = Pt_Time();
+    buffer[0].timestamp = curtime + timestamp;
+    buffer[0].message = Pm_Message(status, data1, data2);
+    if (device == -1 && self->midicount > 1) {
+        for (i=0; i<self->midicount; i++) {
+            Pm_Write(self->midiout[i], buffer, 1);
+        }
+    }
+    else if (self->midicount == 1)
+        Pm_Write(self->midiout[0], buffer, 1);
+    else {
+        for (i=0; i<self->midicount; i++) {
+            if (self->ids[i] == device) {
+                device = i;
+                break;
+            }
+        }
+        if (device < 0 || device >= self->midicount)
+            device = 0;
+        Pm_Write(self->midiout[device], buffer, 1);
+    }
+
+    Py_RETURN_NONE;
+}
+
+PyObject *
+MidiDispatcher_getDeviceInfos(MidiDispatcher *self) {
+    int i;
+    PyObject *str;
+    PyObject *lst = PyList_New(0);
+    for (i = 0; i < self->midicount; i++) {
+        const PmDeviceInfo *info = Pm_GetDeviceInfo(self->ids[i]);
+        str = PyBytes_FromFormat("id: %d, name: %s, interface: %s\n", self->ids[i], info->name, info->interf);
+        PyList_Append(lst, str);
+    }
+    return lst;
+}
+
+static PyMemberDef MidiDispatcher_members[] = {
+    {NULL}  /* Sentinel */
+};
+
+static PyMethodDef MidiDispatcher_methods[] = {
+    {"play", (PyCFunction)MidiDispatcher_play, METH_NOARGS, "Starts computing without sending sound to soundcard."},
+    {"stop", (PyCFunction)MidiDispatcher_stop, METH_NOARGS, "Stops computing."},
+    {"getDeviceInfos", (PyCFunction)MidiDispatcher_getDeviceInfos, METH_NOARGS, "Returns a list of device infos."},
+    {"send", (PyCFunction)MidiDispatcher_send, METH_VARARGS, "Send a raw midi event."},
+    {NULL}  /* Sentinel */
+};
+
+PyTypeObject MidiDispatcherType = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "_pyo.MidiDispatcher_base",         /*tp_name*/
+    sizeof(MidiDispatcher),         /*tp_basicsize*/
+    0,                         /*tp_itemsize*/
+    (destructor)MidiDispatcher_dealloc, /*tp_dealloc*/
+    0,                         /*tp_print*/
+    0,                         /*tp_getattr*/
+    0,                         /*tp_setattr*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
+    0,                         /*tp_repr*/
+    0,             /*tp_as_number*/
+    0,                         /*tp_as_sequence*/
+    0,                         /*tp_as_mapping*/
+    0,                         /*tp_hash */
+    0,                         /*tp_call*/
+    0,                         /*tp_str*/
+    0,                         /*tp_getattro*/
+    0,                         /*tp_setattro*/
+    0,                         /*tp_as_buffer*/
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
+    "MidiDispatcher objects. Calls a function with midi data as arguments.",           /* tp_doc */
+    (traverseproc)MidiDispatcher_traverse,   /* tp_traverse */
+    (inquiry)MidiDispatcher_clear,           /* tp_clear */
+    0,		               /* tp_richcompare */
+    0,		               /* tp_weaklistoffset */
+    0,		               /* tp_iter */
+    0,		               /* tp_iternext */
+    MidiDispatcher_methods,             /* tp_methods */
+    MidiDispatcher_members,             /* tp_members */
+    0,                      /* tp_getset */
+    0,                         /* tp_base */
+    0,                         /* tp_dict */
+    0,                         /* tp_descr_get */
+    0,                         /* tp_descr_set */
+    0,                         /* tp_dictoffset */
+    0,      /* tp_init */
+    0,                         /* tp_alloc */
+    MidiDispatcher_new,                 /* tp_new */
+};
diff --git a/src/engine/pyomodule.c b/src/engine/pyomodule.c
index cdb1f59..7b3da65 100644
--- a/src/engine/pyomodule.c
+++ b/src/engine/pyomodule.c
@@ -1899,6 +1899,7 @@ init_pyo64(void)
     module_add_object(m, "Server_base", &ServerType);
 #ifdef USE_PORTMIDI
     module_add_object(m, "MidiListener_base", &MidiListenerType);
+    module_add_object(m, "MidiDispatcher_base", &MidiDispatcherType);
 #endif
 #ifdef USE_OSC
     module_add_object(m, "OscListener_base", &OscListenerType);
@@ -2197,12 +2198,17 @@ init_pyo64(void)
     module_add_object(m, "PeakAmp_base", &PeakAmpType);
     module_add_object(m, "MainParticle_base", &MainParticleType);
     module_add_object(m, "Particle_base", &ParticleType);
+    module_add_object(m, "MainParticle2_base", &MainParticle2Type);
+    module_add_object(m, "Particle2_base", &Particle2Type);
     module_add_object(m, "AtanTable_base", &AtanTableType);
     module_add_object(m, "RawMidi_base", &RawMidiType);
     module_add_object(m, "Resample_base", &ResampleType);
     module_add_object(m, "Expr_base", &ExprType);
     module_add_object(m, "PadSynthTable_base", &PadSynthTableType);
     module_add_object(m, "LogiMap_base", &LogiMapType);
+    module_add_object(m, "SharedTable_base", &SharedTableType);
+    module_add_object(m, "TableFill_base", &TableFillType);
+    module_add_object(m, "TableScan_base", &TableScanType);
 
     PyModule_AddStringConstant(m, "PYO_VERSION", PYO_VERSION);
 #ifdef COMPILE_EXTERNALS
diff --git a/src/engine/servermodule.c b/src/engine/servermodule.c
index 3f8e329..82a00f7 100644
--- a/src/engine/servermodule.c
+++ b/src/engine/servermodule.c
@@ -485,60 +485,6 @@ Server_process_time(Server *server)
     }
 }
 
-PyObject *
-Server_shut_down(Server *self)
-{
-    int i;
-    int ret = -1;
-    if (self->server_booted == 0) {
-        Server_error(self, "The Server must be booted!\n");
-        Py_RETURN_NONE;
-    }
-    if (self->server_started == 1) {
-        Server_stop((Server *)self);
-    }
-
-    for (i=0; i<num_rnd_objs; i++) {
-        rnd_objs_count[i] = 0;
-    }
-
-    switch (self->midi_be_type) {
-        case PyoPortmidi:
-            if (self->withPortMidi == 1 || self->withPortMidiOut == 1)
-                ret = Server_pm_deinit(self);
-            break;
-        default:
-            break;
-    }
-
-    switch (self->audio_be_type) {
-        case PyoPortaudio:
-            ret = Server_pa_deinit(self);
-            break;
-        case PyoCoreaudio:
-            ret = Server_coreaudio_deinit(self);
-            break;
-        case PyoJack:
-            ret = Server_jack_deinit(self);
-            break;
-        case PyoOffline:
-            ret = Server_offline_deinit(self);
-            break;
-        case PyoOfflineNB:
-            ret = Server_offline_deinit(self);
-            break;
-        case PyoEmbedded:
-            ret = Server_embedded_deinit(self);
-            break;
-    }
-    self->server_booted = 0;
-    if (ret < 0) {
-        Server_error(self, "Error closing audio backend.\n");
-    }
-
-    Py_RETURN_NONE;
-}
-
 static int
 Server_traverse(Server *self, visitproc visit, void *arg)
 {
@@ -569,7 +515,7 @@ static void
 Server_dealloc(Server* self)
 {
     if (self->server_booted == 1)
-        Server_shut_down(self);
+        Server_shutdown(self);
     Server_clear(self);
     free(self->input_buffer);
     free(self->output_buffer);
@@ -638,7 +584,7 @@ Server_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->midi_output = -1;
     self->midiActive = 1;
     self->amp = self->resetAmp = 1.;
-    self->currentAmp = self->lastAmp = 0.;
+    self->currentAmp = self->lastAmp = 1.; // If set to 0, there is a 5ms fadein at server start.
     self->withGUI = 0;
     self->withTIME = 0;
     self->verbosity = 7;
@@ -646,6 +592,8 @@ Server_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->recformat = 0;
     self->rectype = 0;
     self->recquality = 0.4;
+    self->globalDur = 0.0;
+    self->globalDel = 0.0;
     self->startoffset = 0.0;
     self->globalSeed = 0;
     self->CALLBACK = NULL;
@@ -873,6 +821,24 @@ Server_setBufferSize(Server *self, PyObject *arg)
 }
 
 static PyObject *
+Server_setGlobalDur(Server *self, PyObject *arg)
+{
+    if (arg != NULL && PyNumber_Check(arg)) {
+        self->globalDur = PyFloat_AsDouble(arg);
+    }
+    Py_RETURN_NONE;
+}
+
+static PyObject *
+Server_setGlobalDel(Server *self, PyObject *arg)
+{
+    if (arg != NULL && PyNumber_Check(arg)) {
+        self->globalDel = PyFloat_AsDouble(arg);
+    }
+    Py_RETURN_NONE;
+}
+
+static PyObject *
 Server_setDuplex(Server *self, PyObject *arg)
 {
     if (self->server_booted) {
@@ -1082,11 +1048,67 @@ Server_setStartOffset(Server *self, PyObject *arg)
     Py_RETURN_NONE;
 }
 
+/*******************************************/
+/** Server shutdown / boot / start / stop **/
+/*******************************************/
+
+PyObject *
+Server_shutdown(Server *self)
+{
+    int i, ret = -1;
+    if (self->server_booted == 0) {
+        Server_error(self, "The Server must be booted!\n");
+        Py_RETURN_NONE;
+    }
+    if (self->server_started == 1) {
+        Server_stop((Server *)self);
+    }
+
+    for (i=0; i<num_rnd_objs; i++) {
+        rnd_objs_count[i] = 0;
+    }
+
+    switch (self->midi_be_type) {
+        case PyoPortmidi:
+            if (self->withPortMidi == 1 || self->withPortMidiOut == 1)
+                ret = Server_pm_deinit(self);
+            break;
+        default:
+            break;
+    }
+
+    switch (self->audio_be_type) {
+        case PyoPortaudio:
+            ret = Server_pa_deinit(self);
+            break;
+        case PyoCoreaudio:
+            ret = Server_coreaudio_deinit(self);
+            break;
+        case PyoJack:
+            ret = Server_jack_deinit(self);
+            break;
+        case PyoOffline:
+            ret = Server_offline_deinit(self);
+            break;
+        case PyoOfflineNB:
+            ret = Server_offline_deinit(self);
+            break;
+        case PyoEmbedded:
+            ret = Server_embedded_deinit(self);
+            break;
+    }
+    self->server_booted = 0;
+    if (ret < 0) {
+        Server_error(self, "Error closing audio backend.\n");
+    }
+
+    Py_RETURN_NONE;
+}
+
 static PyObject *
 Server_boot(Server *self, PyObject *arg)
 {
-    int audioerr = 0, midierr = 0;
-    int i;
+    int i, audioerr = 0, midierr = 0;
     if (self->server_booted == 1) {
         Server_error(self, "Server already booted!\n");
         Py_RETURN_NONE;
@@ -1095,6 +1117,11 @@ Server_boot(Server *self, PyObject *arg)
     self->stream_count = 0;
     self->elapsedSamples = 0;
 
+    /* Ensure Python is set up for threading */
+    if (!PyEval_ThreadsInitialized()) {
+        PyEval_InitThreads();
+    }
+
     int needNewBuffer = 0;
     if (arg != NULL && PyBool_Check(arg)) {
         needNewBuffer = PyObject_IsTrue(arg);
@@ -1205,14 +1232,9 @@ Server_start(Server *self)
 
     Server_debug(self, "Server_start: number of streams %d\n", self->stream_count);
 
-    /* Ensure Python is set up for threading */
-    if (!PyEval_ThreadsInitialized()) {
-        PyEval_InitThreads();
-    }
-
     self->server_stopped = 0;
     self->server_started = 1;
-    self->timeStep = (int)(0.01 * self->samplingRate);
+    self->timeStep = (int)(0.005 * self->samplingRate);
 
     if (self->startoffset > 0.0) {
         Server_message(self,"Rendering %.2f seconds offline...\n", self->startoffset);
@@ -1282,11 +1304,12 @@ Server_stop(Server *self)
     }
     else {
         self->server_stopped = 1;
+        self->server_started = 0;
     }
 
     /* This call is needed to recover from thread fork with python3/jack on debian.*/
     /* TODO: Need to be tested with other OSes and audio driver. */
-    PyOS_AfterFork();
+    //PyOS_AfterFork();
 
     Py_RETURN_NONE;
 }
@@ -1735,6 +1758,18 @@ Server_getBufferSize(Server *self)
 }
 
 static PyObject *
+Server_getGlobalDur(Server *self)
+{
+    return PyFloat_FromDouble(self->globalDur);
+}
+
+static PyObject *
+Server_getGlobalDel(Server *self)
+{
+    return PyFloat_FromDouble(self->globalDel);
+}
+
+static PyObject *
 Server_beginResamplingBlock(Server *self, PyObject *arg)
 {
     if (PyInt_Check(arg)) {
@@ -1894,6 +1929,8 @@ static PyMethodDef Server_methods[] = {
     {"deactivateMidi", (PyCFunction)Server_deactivateMidi, METH_NOARGS, "Deactivates midi callback."},
     {"setSamplingRate", (PyCFunction)Server_setSamplingRate, METH_O, "Sets the server's sampling rate."},
     {"setBufferSize", (PyCFunction)Server_setBufferSize, METH_O, "Sets the server's buffer size."},
+    {"setGlobalDur", (PyCFunction)Server_setGlobalDur, METH_O, "Sets the server's globalDur attribute."},
+    {"setGlobalDel", (PyCFunction)Server_setGlobalDel, METH_O, "Sets the server's globalDel attribute."},
     {"beginResamplingBlock", (PyCFunction)Server_beginResamplingBlock, METH_O, "Starts a resampling code block."},
     {"endResamplingBlock", (PyCFunction)Server_endResamplingBlock, METH_NOARGS, "Stops a resampling code block."},
     {"setNchnls", (PyCFunction)Server_setNchnls, METH_O, "Sets the server's number of output/input channels."},
@@ -1910,7 +1947,7 @@ static PyMethodDef Server_methods[] = {
     {"setVerbosity", (PyCFunction)Server_setVerbosity, METH_O, "Sets the verbosity."},
     {"setStartOffset", (PyCFunction)Server_setStartOffset, METH_O, "Sets starting time offset."},
     {"boot", (PyCFunction)Server_boot, METH_O, "Setup and boot the server."},
-    {"shutdown", (PyCFunction)Server_shut_down, METH_NOARGS, "Shut down the server."},
+    {"shutdown", (PyCFunction)Server_shutdown, METH_NOARGS, "Shut down the server."},
     {"start", (PyCFunction)Server_start, METH_NOARGS, "Starts the server's callback loop."},
     {"stop", (PyCFunction)Server_stop, METH_NOARGS, "Stops the server's callback loop."},
     {"recordOptions", (PyCFunction)Server_recordOptions, METH_VARARGS|METH_KEYWORDS, "Sets format settings for offline rendering and global recording."},
@@ -1936,6 +1973,8 @@ static PyMethodDef Server_methods[] = {
     {"getIchnls", (PyCFunction)Server_getIchnls, METH_NOARGS, "Returns the server's current number of input channels."},
     {"getGlobalSeed", (PyCFunction)Server_getGlobalSeed, METH_NOARGS, "Returns the server's global seed."},
     {"getBufferSize", (PyCFunction)Server_getBufferSize, METH_NOARGS, "Returns the server's buffer size."},
+    {"getGlobalDur", (PyCFunction)Server_getGlobalDur, METH_NOARGS, "Returns the server's globalDur attribute."},
+    {"getGlobalDel", (PyCFunction)Server_getGlobalDel, METH_NOARGS, "Returns the server's globalDel attribute."},
     {"getIsBooted", (PyCFunction)Server_getIsBooted, METH_NOARGS, "Returns 1 if the server is booted, otherwise returns 0."},
     {"getIsStarted", (PyCFunction)Server_getIsStarted, METH_NOARGS, "Returns 1 if the server is started, otherwise returns 0."},
     {"getMidiActive", (PyCFunction)Server_getMidiActive, METH_NOARGS, "Returns 1 if midi callback is active, otherwise returns 0."},
diff --git a/src/objects/fadermodule.c b/src/objects/fadermodule.c
index b48c754..2a7519b 100644
--- a/src/objects/fadermodule.c
+++ b/src/objects/fadermodule.c
@@ -36,6 +36,8 @@ typedef struct {
     MYFLT release;
     MYFLT duration;
     MYFLT exp;
+    MYFLT offset;
+    MYFLT currentVal;
     double currentTime;
     MYFLT sampleToSec;
 } Fader;
@@ -65,7 +67,7 @@ Fader_generate_auto(Fader *self) {
 
     for (i=0; i<self->bufsize; i++) {
         if (self->currentTime <= self->attack)
-            val = self->currentTime * iatt;
+            val = self->currentTime * iatt * (1.0 - self->offset) + self->offset;
         else if (self->currentTime > self->duration) {
             val = 0.;
             self->ended = 1;
@@ -75,7 +77,7 @@ Fader_generate_auto(Fader *self) {
         else
             val = 1.;
 
-        self->data[i] = val;
+        self->data[i] = self->currentVal = val;
         self->currentTime += self->sampleToSec;
     }
 
@@ -101,9 +103,8 @@ Fader_generate_wait(Fader *self) {
 
     for (i=0; i<self->bufsize; i++) {
         if (self->fademode == 0) {
-
             if (self->currentTime <= self->attack)
-                val = self->currentTime * iatt;
+                val = self->currentTime * iatt * (1.0 - self->offset) + self->offset;
             else
                 val = 1.;
             self->topValue = val;
@@ -114,7 +115,7 @@ Fader_generate_wait(Fader *self) {
             else
                 val = 0.;
         }
-        self->data[i] = val;
+        self->data[i] = self->currentVal = val;
         self->currentTime += self->sampleToSec;
     }
     
@@ -224,13 +225,13 @@ Fader_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->duration = 0.0;
     self->exp = 1.0;
     self->currentTime = 0.0;
+    self->offset = 0.0;
+    self->currentVal = 0.0;
 
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Fader_compute_next_data_frame);
     self->mode_func_ptr = Fader_setProcMode;
 
-    Stream_setStreamActive(self->stream, 0);
-
     self->sampleToSec = 1. / self->sr;
 
     static char *kwlist[] = {"fadein", "fadeout", "dur", "mul", "add", NULL};
@@ -265,6 +266,7 @@ static PyObject * Fader_play(Fader *self, PyObject *args, PyObject *kwds)
     self->fademode = 0;
     self->ended = 0;
     self->currentTime = 0.0;
+    self->offset = self->currentVal;
     (*self->mode_func_ptr)(self);
     PLAY
 };
@@ -444,6 +446,8 @@ typedef struct {
     MYFLT release;
     MYFLT duration;
     MYFLT exp;
+    MYFLT offset;
+    MYFLT currentVal;
     double currentTime;
     MYFLT sampleToSec;
 } Adsr;
@@ -472,7 +476,7 @@ Adsr_generate_auto(Adsr *self) {
 
     for (i=0; i<self->bufsize; i++) {
         if (self->currentTime <= self->attack)
-            val = self->currentTime * invatt;
+            val = self->currentTime * invatt * (1.0 - self->offset) + self->offset;
         else if (self->currentTime <= (self->attack + self->decay))
             val = (self->decay - (self->currentTime - self->attack)) * invdec * (1. - self->sustain) + self->sustain;
         else if (self->currentTime > self->duration)
@@ -482,7 +486,7 @@ Adsr_generate_auto(Adsr *self) {
         else
             val = self->sustain;
 
-        self->data[i] = val;
+        self->data[i] = self->currentVal = val;
         self->currentTime += self->sampleToSec;
     }
 
@@ -507,9 +511,8 @@ Adsr_generate_wait(Adsr *self) {
 
     for (i=0; i<self->bufsize; i++) {
         if (self->fademode == 0) {
-
             if (self->currentTime <= self->attack)
-                val = self->currentTime * invatt;
+                val = self->currentTime * invatt * (1.0 - self->offset) + self->offset;
             else if (self->currentTime <= (self->attack + self->decay))
                 val = (self->decay - (self->currentTime - self->attack)) * invdec * (1. - self->sustain) + self->sustain;
             else
@@ -523,7 +526,7 @@ Adsr_generate_wait(Adsr *self) {
             else
                 val = 0.;
         }
-        self->data[i] = val;
+        self->data[i] = self->currentVal = val;
         self->currentTime += self->sampleToSec;
     }
 
@@ -634,13 +637,13 @@ Adsr_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->duration = 0.0;
     self->exp = 1.0;
     self->currentTime = 0.0;
+    self->offset = 0.0;
+    self->currentVal = 0.0;
 
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Adsr_compute_next_data_frame);
     self->mode_func_ptr = Adsr_setProcMode;
 
-    Stream_setStreamActive(self->stream, 0);
-
     self->sampleToSec = 1. / self->sr;
 
     static char *kwlist[] = {"attack", "decay", "sustain", "release", "dur", "mul", "add", NULL};
@@ -685,6 +688,7 @@ static PyObject * Adsr_play(Adsr *self, PyObject *args, PyObject *kwds)
 {
     self->fademode = 0;
     self->currentTime = 0.0;
+    self->offset = self->currentVal;
     (*self->mode_func_ptr)(self);
     PLAY
 };
@@ -1072,8 +1076,6 @@ Linseg_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     Stream_setFunctionPtr(self->stream, Linseg_compute_next_data_frame);
     self->mode_func_ptr = Linseg_setProcMode;
 
-    Stream_setStreamActive(self->stream, 0);
-
     self->sampleToSec = 1. / self->sr;
 
     static char *kwlist[] = {"list", "loop", "initToFirstVal", "mul", "add", NULL};
@@ -1489,8 +1491,6 @@ Expseg_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     Stream_setFunctionPtr(self->stream, Expseg_compute_next_data_frame);
     self->mode_func_ptr = Expseg_setProcMode;
 
-    Stream_setStreamActive(self->stream, 0);
-
     self->sampleToSec = 1. / self->sr;
 
     static char *kwlist[] = {"list", "loop", "exp", "inverse", "initToFirstVal", "mul", "add", NULL};
diff --git a/src/objects/granulatormodule.c b/src/objects/granulatormodule.c
index f459b22..78db68b 100644
--- a/src/objects/granulatormodule.c
+++ b/src/objects/granulatormodule.c
@@ -4578,4 +4578,1729 @@ Particle_members,             /* tp_members */
 0,      /* tp_init */
 0,                         /* tp_alloc */
 Particle_new,                 /* tp_new */
+};
+
+typedef struct {
+    pyo_audio_HEAD
+    PyObject *table;
+    PyObject *env;
+    PyObject *dens;
+    Stream *dens_stream;
+    PyObject *pitch;
+    Stream *pitch_stream;
+    PyObject *pos;
+    Stream *pos_stream;
+    PyObject *dur;
+    Stream *dur_stream;
+    PyObject *dev;
+    Stream *dev_stream;
+    PyObject *pan;
+    Stream *pan_stream;
+
+    PyObject *filterfreq;
+    Stream *filterfreq_stream;
+    PyObject *filterq;
+    Stream *filterq_stream;
+    PyObject *filtertype;
+    Stream *filtertype_stream;
+    // filters last values
+    MYFLT *last_freq;
+    MYFLT *last_q;
+    MYFLT *last_type;
+    // sample memories
+    MYFLT *x1;
+    MYFLT *x2;
+    MYFLT *y1;
+    MYFLT *y2;
+    // variables
+    MYFLT *c;
+    MYFLT *w0;
+    MYFLT *alpha;
+    MYFLT *qcomp;
+    // coefficients
+    MYFLT *b0;
+    MYFLT *b1;
+    MYFLT *b2;
+    MYFLT *a0;
+    MYFLT *a1;
+    MYFLT *a2;
+
+    MYFLT *gpos;
+    MYFLT *glen;
+    MYFLT *inc;
+    MYFLT *phase;
+    MYFLT *amp1;
+    MYFLT *amp2;
+    int *flags;
+    int *k1;
+    int *k2;
+    int num;
+    int chnls;
+    double timer;
+    double devFactor;
+    double srScale;
+    MYFLT oneOnSr;
+    MYFLT nyquist;
+    MYFLT twopiOverSr;
+    MYFLT srOnRandMax;
+    MYFLT *buffer_streams;
+    int modebuffer[9];
+} MainParticle2;
+
+static void
+MainParticle2_compute_coeffs_lp(MainParticle2 *self, int which)
+{
+    self->b0[which] = self->b2[which] = (1 - self->c[which]) / 2;
+    self->b1[which] = 1 - self->c[which];
+    self->a0[which] = 1.0 / (1 + self->alpha[which]);
+    self->a1[which] = -2 * self->c[which];
+    self->a2[which] = 1 - self->alpha[which];
+}
+
+static void
+MainParticle2_compute_coeffs_hp(MainParticle2 *self, int which)
+{
+    self->b0[which] = self->b2[which] = (1 + self->c[which]) / 2;
+    self->b1[which] = -(1 + self->c[which]);
+    self->a0[which] = 1.0 / (1 + self->alpha[which]);
+    self->a1[which] = -2 * self->c[which];
+    self->a2[which] = 1 - self->alpha[which];
+}
+
+static void
+MainParticle2_compute_coeffs_bp(MainParticle2 *self, int which)
+{
+    self->b0[which] = self->alpha[which];
+    self->b1[which] = 0;
+    self->b2[which] = -self->alpha[which];
+    self->a0[which] = 1.0 / (1 + self->alpha[which]);
+    self->a1[which] = -2 * self->c[which];
+    self->a2[which] = 1 - self->alpha[which];
+}
+
+static void
+MainParticle2_compute_coeffs_bs(MainParticle2 *self, int which)
+{
+    self->b0[which] = self->b2[which] = 1;
+    self->b1[which] = self->a1[which] = -2 * self->c[which];
+    self->a0[which] = 1.0 / (1 + self->alpha[which]);
+    self->a2[which] = 1 - self->alpha[which];
+}
+
+static void
+MainParticle2_compute_coeffs_ap(MainParticle2 *self, int which)
+{
+    self->b0[which] = self->a2[which] = 1 - self->alpha[which];
+    self->b1[which] = self->a1[which] = -2 * self->c[which];
+    self->b2[which] = 1 + self->alpha[which];
+    self->a0[which] = 1.0 / (1 + self->alpha[which]);
+}
+
+static void
+MainParticle2_compute_variables(MainParticle2 *self, MYFLT freq, MYFLT q, int which)
+{
+    self->w0[which] = freq * self->twopiOverSr;
+    self->c[which] = MYCOS(self->w0[which]);
+    self->alpha[which] = MYSIN(self->w0[which]) / (2 * q);
+}
+
+static void
+MainParticle2_transform_mono_i(MainParticle2 *self) {
+    MYFLT dens, inc, index, amp, phase, val, fval;
+    int i, j, ipart, flag = 0;
+    MYFLT pit = 0, pos = 0, dur = 0, dev = 0, filterfreq = 0, filterq = 0, filtertype = 0;
+
+    MYFLT *tablelist = TableStream_getData(self->table);
+    int size = TableStream_getSize(self->table);
+
+    MYFLT *envlist = TableStream_getData(self->env);
+    int envsize = TableStream_getSize(self->env);
+
+    dens = PyFloat_AS_DOUBLE(self->dens);
+    if (dens < 0.0)
+        dens = 0.0;
+
+    inc = dens * self->oneOnSr * self->devFactor;
+
+    for (i=0; i<self->bufsize*self->chnls; i++) {
+        self->buffer_streams[i] = 0.0;
+    }
+
+    for (i=0; i<self->bufsize; i++) {
+        self->timer += inc;
+        if (self->timer >= 1.0) {
+            self->timer -= 1.0;
+            flag = 1;
+        }
+
+        /* need to start a new grain */
+        if (flag) {
+            for (j=0; j<MAINPARTICLE_MAX_GRAINS; j++) {
+                if (self->flags[j] == 0) {
+                    self->flags[j] = 1;
+                    if (j >= self->num)
+                        self->num = j + 1;
+                    if (self->modebuffer[1] == 0)
+                        pit = PyFloat_AS_DOUBLE(self->pitch);
+                    else
+                        pit = Stream_getData((Stream *)self->pitch_stream)[i];
+                    if (self->modebuffer[2] == 0)
+                        pos = PyFloat_AS_DOUBLE(self->pos);
+                    else
+                        pos = Stream_getData((Stream *)self->pos_stream)[i];
+                    if (self->modebuffer[3] == 0)
+                        dur = PyFloat_AS_DOUBLE(self->dur);
+                    else
+                        dur = Stream_getData((Stream *)self->dur_stream)[i];
+                    if (self->modebuffer[4] == 0)
+                        dev = PyFloat_AS_DOUBLE(self->dev);
+                    else
+                        dev = Stream_getData((Stream *)self->dev_stream)[i];
+                    if (self->modebuffer[6] == 0)
+                        filterfreq = PyFloat_AS_DOUBLE(self->filterfreq);
+                    else
+                        filterfreq = Stream_getData((Stream *)self->filterfreq_stream)[i];
+                    if (self->modebuffer[7] == 0)
+                        filterq = PyFloat_AS_DOUBLE(self->filterq);
+                    else
+                        filterq = Stream_getData((Stream *)self->filterq_stream)[i];
+                    if (self->modebuffer[8] == 0)
+                        filtertype = PyFloat_AS_DOUBLE(self->filtertype);
+                    else
+                        filtertype = Stream_getData((Stream *)self->filtertype_stream)[i];
+                    if (pit < 0.0)
+                        pit = -pit;
+                    if (pos < 0.0)
+                        pos = 0.0;
+                    else if (pos >= size)
+                        pos = (MYFLT)size;
+                    if (dur < 0.0001)
+                        dur = 0.0001;
+                    if (dev < 0.0)
+                        dev = 0.0;
+                    else if (dev > 1.0)
+                        dev = 1.0;
+                    if (filterfreq < 1.0)
+                        filterfreq = 1.0;
+                    else if (filterfreq > self->nyquist)
+                        filterfreq = self->nyquist;
+                    if (filterq < 0.1)
+                        filterq = 0.1;
+                    if (filtertype < 0)
+                        filtertype = 0;
+                    else if (filtertype > 4)
+                        filtertype = 4;
+                    filtertype = MYROUND(filtertype);
+                    self->gpos[j] = pos;
+                    self->glen[j] = dur * self->sr * pit * self->srScale;
+                    if ((pos + self->glen[j]) >= size || (pos + self->glen[j]) < 0)
+                        self->flags[j] = 0;
+                    self->phase[j] = 0.0;
+                    self->inc[j] = 1.0 / (dur * self->sr);
+                    self->devFactor = (RANDOM_UNIFORM * 2.0 - 1.0) * dev + 1.0;
+                    if (filtertype != self->last_type[j] || filterfreq != self->last_freq[j] || filterq != self->last_q[j]) {
+                        self->last_freq[j] = filterfreq;
+                        self->last_q[j] = filterq;
+                        self->last_type[j] = filtertype;
+                        MainParticle2_compute_variables(self, filterfreq, filterq, j);
+                        self->qcomp[j] = 1.0;
+                        self->b0[j] = self->b1[j] = self->b2[j] = self->a0[j] = self->a1[j] = self->a2[j] = 0.0;
+                        if (filtertype == 0)
+                            MainParticle2_compute_coeffs_lp(self, j);
+                        else if (filtertype == 1)
+                            MainParticle2_compute_coeffs_hp(self, j);
+                        else if (filtertype == 2) {
+                            MainParticle2_compute_coeffs_bp(self, j);
+                            filterq = filterq < 10.0 ? filterq : 10.0;
+                            self->qcomp[j] = MYPOW(10, (filterq - 1) * 0.1);
+                        }
+                        else if (filtertype == 3)
+                            MainParticle2_compute_coeffs_bs(self, j);
+                        else if (filtertype == 4)
+                            MainParticle2_compute_coeffs_ap(self, j);
+                    }
+                    break;
+                }
+            }
+        }
+
+        /* compute active grains */
+        for (j=0; j<self->num; j++) {
+            if (self->flags[j]) {
+                phase = self->phase[j];
+                /* compute envelope */
+                index = phase * envsize;
+                ipart = (int)index;
+                amp = envlist[ipart] + (envlist[ipart+1] - envlist[ipart]) * (index - ipart);
+                /* compute sampling */
+                index = phase * self->glen[j] + self->gpos[j];
+                ipart = (int)index;
+                val = (tablelist[ipart] + (tablelist[ipart+1] - tablelist[ipart]) * (index - ipart));
+                /* filtering */
+                fval = ( (self->b0[j] * val) + (self->b1[j] * self->x1[j]) + (self->b2[j] * self->x2[j]) - (self->a1[j] * self->y1[j]) - (self->a2[j] * self->y2[j]) ) * self->a0[j];
+                self->y2[j] = self->y1[j];
+                self->y1[j] = fval;
+                self->x2[j] = self->x1[j];
+                self->x1[j] = val;
+                fval *= self->qcomp[j];
+                /* Add to output streams */
+                fval *= amp;
+                self->buffer_streams[i] += fval;
+                phase += self->inc[j];
+                if (phase >= 1.0)
+                    self->flags[j] = 0;
+                else
+                    self->phase[j] = phase;
+            }
+        }
+        flag = 0;
+    }
+}
+
+static void
+MainParticle2_transform_mono_a(MainParticle2 *self) {
+    MYFLT dens, index, amp, phase, val, fval;
+    int i, j, ipart, flag = 0;
+    MYFLT pit = 0, pos = 0, dur = 0, dev = 0, filterfreq = 0, filterq = 0, filtertype = 0;
+
+    MYFLT *tablelist = TableStream_getData(self->table);
+    int size = TableStream_getSize(self->table);
+
+    MYFLT *envlist = TableStream_getData(self->env);
+    int envsize = TableStream_getSize(self->env);
+
+    MYFLT *density = Stream_getData((Stream *)self->dens_stream);
+
+    for (i=0; i<self->bufsize*self->chnls; i++) {
+        self->buffer_streams[i] = 0.0;
+    }
+
+    for (i=0; i<self->bufsize; i++) {
+        if (density[i] < 0.0)
+            dens = 0.0;
+        else
+            dens = density[i];
+        self->timer += dens * self->oneOnSr * self->devFactor;
+        if (self->timer >= 1.0) {
+            self->timer -= 1.0;
+            flag = 1;
+        }
+
+        /* need to start a new grain */
+        if (flag) {
+            for (j=0; j<MAINPARTICLE_MAX_GRAINS; j++) {
+                if (self->flags[j] == 0) {
+                    self->flags[j] = 1;
+                    if (j >= self->num)
+                        self->num = j + 1;
+                    if (self->modebuffer[1] == 0)
+                        pit = PyFloat_AS_DOUBLE(self->pitch);
+                    else
+                        pit = Stream_getData((Stream *)self->pitch_stream)[i];
+                    if (self->modebuffer[2] == 0)
+                        pos = PyFloat_AS_DOUBLE(self->pos);
+                    else
+                        pos = Stream_getData((Stream *)self->pos_stream)[i];
+                    if (self->modebuffer[3] == 0)
+                        dur = PyFloat_AS_DOUBLE(self->dur);
+                    else
+                        dur = Stream_getData((Stream *)self->dur_stream)[i];
+                    if (self->modebuffer[4] == 0)
+                        dev = PyFloat_AS_DOUBLE(self->dev);
+                    else
+                        dev = Stream_getData((Stream *)self->dev_stream)[i];
+                    if (self->modebuffer[6] == 0)
+                        filterfreq = PyFloat_AS_DOUBLE(self->filterfreq);
+                    else
+                        filterfreq = Stream_getData((Stream *)self->filterfreq_stream)[i];
+                    if (self->modebuffer[7] == 0)
+                        filterq = PyFloat_AS_DOUBLE(self->filterq);
+                    else
+                        filterq = Stream_getData((Stream *)self->filterq_stream)[i];
+                    if (self->modebuffer[8] == 0)
+                        filtertype = PyFloat_AS_DOUBLE(self->filtertype);
+                    else
+                        filtertype = Stream_getData((Stream *)self->filtertype_stream)[i];
+                    if (pit < 0.0)
+                        pit = -pit;
+                    if (pos < 0.0)
+                        pos = 0.0;
+                    else if (pos >= size)
+                        pos = (MYFLT)size;
+                    if (dur < 0.0001)
+                        dur = 0.0001;
+                    if (dev < 0.0)
+                        dev = 0.0;
+                    else if (dev > 1.0)
+                        dev = 1.0;
+                    if (filterfreq < 1.0)
+                        filterfreq = 1.0;
+                    else if (filterfreq > self->nyquist)
+                        filterfreq = self->nyquist;
+                    if (filterq < 0.1)
+                        filterq = 0.1;
+                    if (filtertype < 0)
+                        filtertype = 0;
+                    else if (filtertype > 4)
+                        filtertype = 4;
+                    filtertype = MYROUND(filtertype);
+                    self->gpos[j] = pos;
+                    self->glen[j] = dur * self->sr * pit * self->srScale;
+                    if ((pos + self->glen[j]) >= size || (pos + self->glen[j]) < 0)
+                        self->flags[j] = 0;
+                    self->phase[j] = 0.0;
+                    self->inc[j] = 1.0 / (dur * self->sr);
+                    self->devFactor = (RANDOM_UNIFORM * 2.0 - 1.0) * dev + 1.0;
+                    if (filtertype != self->last_type[j] || filterfreq != self->last_freq[j] || filterq != self->last_q[j]) {
+                        self->last_freq[j] = filterfreq;
+                        self->last_q[j] = filterq;
+                        self->last_type[j] = filtertype;
+                        MainParticle2_compute_variables(self, filterfreq, filterq, j);
+                        self->qcomp[j] = 1.0;
+                        self->b0[j] = self->b1[j] = self->b2[j] = self->a0[j] = self->a1[j] = self->a2[j] = 0.0;
+                        if (filtertype == 0)
+                            MainParticle2_compute_coeffs_lp(self, j);
+                        else if (filtertype == 1)
+                            MainParticle2_compute_coeffs_hp(self, j);
+                        else if (filtertype == 2) {
+                            MainParticle2_compute_coeffs_bp(self, j);
+                            filterq = filterq < 10.0 ? filterq : 10.0;
+                            self->qcomp[j] = MYPOW(10, (filterq - 1) * 0.1);
+                        }
+                        else if (filtertype == 3)
+                            MainParticle2_compute_coeffs_bs(self, j);
+                        else if (filtertype == 4)
+                            MainParticle2_compute_coeffs_ap(self, j);
+                    }
+                    break;
+                }
+            }
+        }
+
+        /* compute active grains */
+        for (j=0; j<self->num; j++) {
+            if (self->flags[j]) {
+                phase = self->phase[j];
+                /* compute envelope */
+                index = phase * envsize;
+                ipart = (int)index;
+                amp = envlist[ipart] + (envlist[ipart+1] - envlist[ipart]) * (index - ipart);
+                /* compute sampling */
+                index = phase * self->glen[j] + self->gpos[j];
+                ipart = (int)index;
+                val = (tablelist[ipart] + (tablelist[ipart+1] - tablelist[ipart]) * (index - ipart));
+                /* filtering */
+                fval = ( (self->b0[j] * val) + (self->b1[j] * self->x1[j]) + (self->b2[j] * self->x2[j]) - (self->a1[j] * self->y1[j]) - (self->a2[j] * self->y2[j]) ) * self->a0[j];
+                self->y2[j] = self->y1[j];
+                self->y1[j] = fval;
+                self->x2[j] = self->x1[j];
+                self->x1[j] = val;
+                fval *= self->qcomp[j];
+                /* Add to output streams */
+                fval *= amp;
+                self->buffer_streams[i] += fval;
+                phase += self->inc[j];
+                if (phase >= 1.0)
+                    self->flags[j] = 0;
+                else
+                    self->phase[j] = phase;
+            }
+        }
+        flag = 0;
+    }
+}
+
+static void
+MainParticle2_transform_i(MainParticle2 *self) {
+    MYFLT dens, inc, index, amp, phase, val, fval, min = 0;
+    int i, j, l, l1, ipart, flag = 0;
+    MYFLT pit = 0, pos = 0, dur = 0, dev = 0, pan = 0, filterfreq = 0, filterq = 0, filtertype = 0;
+
+    MYFLT *tablelist = TableStream_getData(self->table);
+    int size = TableStream_getSize(self->table);
+
+    MYFLT *envlist = TableStream_getData(self->env);
+    int envsize = TableStream_getSize(self->env);
+
+    dens = PyFloat_AS_DOUBLE(self->dens);
+    if (dens < 0.0)
+        dens = 0.0;
+
+    inc = dens * self->oneOnSr * self->devFactor;
+
+    for (i=0; i<self->bufsize*self->chnls; i++) {
+        self->buffer_streams[i] = 0.0;
+    }
+
+    for (i=0; i<self->bufsize; i++) {
+        self->timer += inc;
+        if (self->timer >= 1.0) {
+            self->timer -= 1.0;
+            flag = 1;
+        }
+
+        /* need to start a new grain */
+        if (flag) {
+            for (j=0; j<MAINPARTICLE_MAX_GRAINS; j++) {
+                if (self->flags[j] == 0) {
+                    self->flags[j] = 1;
+                    if (j >= self->num)
+                        self->num = j + 1;
+                    if (self->modebuffer[1] == 0)
+                        pit = PyFloat_AS_DOUBLE(self->pitch);
+                    else
+                        pit = Stream_getData((Stream *)self->pitch_stream)[i];
+                    if (self->modebuffer[2] == 0)
+                        pos = PyFloat_AS_DOUBLE(self->pos);
+                    else
+                        pos = Stream_getData((Stream *)self->pos_stream)[i];
+                    if (self->modebuffer[3] == 0)
+                        dur = PyFloat_AS_DOUBLE(self->dur);
+                    else
+                        dur = Stream_getData((Stream *)self->dur_stream)[i];
+                    if (self->modebuffer[4] == 0)
+                        dev = PyFloat_AS_DOUBLE(self->dev);
+                    else
+                        dev = Stream_getData((Stream *)self->dev_stream)[i];
+                    if (self->modebuffer[5] == 0)
+                        pan = PyFloat_AS_DOUBLE(self->pan);
+                    else
+                        pan = Stream_getData((Stream *)self->pan_stream)[i];
+                    if (self->modebuffer[6] == 0)
+                        filterfreq = PyFloat_AS_DOUBLE(self->filterfreq);
+                    else
+                        filterfreq = Stream_getData((Stream *)self->filterfreq_stream)[i];
+                    if (self->modebuffer[7] == 0)
+                        filterq = PyFloat_AS_DOUBLE(self->filterq);
+                    else
+                        filterq = Stream_getData((Stream *)self->filterq_stream)[i];
+                    if (self->modebuffer[8] == 0)
+                        filtertype = PyFloat_AS_DOUBLE(self->filtertype);
+                    else
+                        filtertype = Stream_getData((Stream *)self->filtertype_stream)[i];
+                    if (pit < 0.0)
+                        pit = -pit;
+                    if (pos < 0.0)
+                        pos = 0.0;
+                    else if (pos >= size)
+                        pos = (MYFLT)size;
+                    if (dur < 0.0001)
+                        dur = 0.0001;
+                    if (dev < 0.0)
+                        dev = 0.0;
+                    else if (dev > 1.0)
+                        dev = 1.0;
+                    if (pan < 0.0)
+                        pan = 0.0;
+                    else if (pan > 1.0)
+                        pan = 1.0;
+                    if (filterfreq < 1.0)
+                        filterfreq = 1.0;
+                    else if (filterfreq > self->nyquist)
+                        filterfreq = self->nyquist;
+                    if (filterq < 0.1)
+                        filterq = 0.1;
+                    if (filtertype < 0)
+                        filtertype = 0;
+                    else if (filtertype > 4)
+                        filtertype = 4;
+                    filtertype = MYROUND(filtertype);
+                    self->gpos[j] = pos;
+                    self->glen[j] = dur * self->sr * pit * self->srScale;
+                    if ((pos + self->glen[j]) >= size || (pos + self->glen[j]) < 0)
+                        self->flags[j] = 0;
+                    self->phase[j] = 0.0;
+                    self->inc[j] = 1.0 / (dur * self->sr);
+                    self->devFactor = (RANDOM_UNIFORM * 2.0 - 1.0) * dev + 1.0;
+                    if (self->chnls == 2) {
+                        self->k1[j] = 0;
+                        self->k2[j] = self->bufsize;
+                        self->amp1[j] = MYSQRT(1.0 - pan);
+                        self->amp2[j] = MYSQRT(pan);
+                    }
+                    else {
+                        self->amp1[j] = MYSQRT(1.0 - pan);
+                        self->amp2[j] = MYSQRT(pan);
+                        min = 0;
+                        self->k1[j] = 0;
+                        self->k2[j] = self->bufsize;
+                        for (l=self->chnls; l>0; l--) {
+                            l1 = l - 1;
+                            min = l1 / (MYFLT)self->chnls;
+                            if (pan > min) {
+                                self->k1[j] = l1 * self->bufsize;
+                                if (l == self->chnls)
+                                    self->k2[j] = 0;
+                                else
+                                    self->k2[j] = l * self->bufsize;
+                                break;
+                            }
+                        }
+                    }
+                    if (filtertype != self->last_type[j] || filterfreq != self->last_freq[j] || filterq != self->last_q[j]) {
+                        self->last_freq[j] = filterfreq;
+                        self->last_q[j] = filterq;
+                        self->last_type[j] = filtertype;
+                        MainParticle2_compute_variables(self, filterfreq, filterq, j);
+                        self->qcomp[j] = 1.0;
+                        self->b0[j] = self->b1[j] = self->b2[j] = self->a0[j] = self->a1[j] = self->a2[j] = 0.0;
+                        if (filtertype == 0)
+                            MainParticle2_compute_coeffs_lp(self, j);
+                        else if (filtertype == 1)
+                            MainParticle2_compute_coeffs_hp(self, j);
+                        else if (filtertype == 2) {
+                            MainParticle2_compute_coeffs_bp(self, j);
+                            filterq = filterq < 10.0 ? filterq : 10.0;
+                            self->qcomp[j] = MYPOW(10, (filterq - 1) * 0.1);
+                        }
+                        else if (filtertype == 3)
+                            MainParticle2_compute_coeffs_bs(self, j);
+                        else if (filtertype == 4)
+                            MainParticle2_compute_coeffs_ap(self, j);
+                    }
+                    break;
+                }
+            }
+        }
+
+        /* compute active grains */
+        for (j=0; j<self->num; j++) {
+            if (self->flags[j]) {
+                phase = self->phase[j];
+                /* compute envelope */
+                index = phase * envsize;
+                ipart = (int)index;
+                amp = envlist[ipart] + (envlist[ipart+1] - envlist[ipart]) * (index - ipart);
+                /* compute sampling */
+                index = phase * self->glen[j] + self->gpos[j];
+                ipart = (int)index;
+                val = (tablelist[ipart] + (tablelist[ipart+1] - tablelist[ipart]) * (index - ipart));
+                /* filtering */
+                fval = ( (self->b0[j] * val) + (self->b1[j] * self->x1[j]) + (self->b2[j] * self->x2[j]) - (self->a1[j] * self->y1[j]) - (self->a2[j] * self->y2[j]) ) * self->a0[j];
+                self->y2[j] = self->y1[j];
+                self->y1[j] = fval;
+                self->x2[j] = self->x1[j];
+                self->x1[j] = val;
+                fval *= self->qcomp[j];
+                /* Add to output streams */
+                fval *= amp;
+                self->buffer_streams[i+self->k1[j]] += fval * self->amp1[j];
+                self->buffer_streams[i+self->k2[j]] += fval * self->amp2[j];
+                phase += self->inc[j];
+                if (phase >= 1.0)
+                    self->flags[j] = 0;
+                else
+                    self->phase[j] = phase;
+            }
+        }
+        flag = 0;
+    }
+}
+
+static void
+MainParticle2_transform_a(MainParticle2 *self) {
+    MYFLT dens, index, amp, phase, val, fval, min = 0;
+    int i, j, l, l1, ipart, flag = 0;
+    MYFLT pit = 0, pos = 0, dur = 0, dev = 0, pan = 0, filterfreq = 0, filterq = 0, filtertype = 0;
+
+    MYFLT *tablelist = TableStream_getData(self->table);
+    int size = TableStream_getSize(self->table);
+
+    MYFLT *envlist = TableStream_getData(self->env);
+    int envsize = TableStream_getSize(self->env);
+
+    MYFLT *density = Stream_getData((Stream *)self->dens_stream);
+
+    for (i=0; i<self->bufsize*self->chnls; i++) {
+        self->buffer_streams[i] = 0.0;
+    }
+
+    for (i=0; i<self->bufsize; i++) {
+        if (density[i] < 0.0)
+            dens = 0.0;
+        else
+            dens = density[i];
+        self->timer += dens * self->oneOnSr * self->devFactor;
+        if (self->timer >= 1.0) {
+            self->timer -= 1.0;
+            flag = 1;
+        }
+
+        /* need to start a new grain */
+        if (flag) {
+            for (j=0; j<MAINPARTICLE_MAX_GRAINS; j++) {
+                if (self->flags[j] == 0) {
+                    self->flags[j] = 1;
+                    if (j >= self->num)
+                        self->num = j + 1;
+                    if (self->modebuffer[1] == 0)
+                        pit = PyFloat_AS_DOUBLE(self->pitch);
+                    else
+                        pit = Stream_getData((Stream *)self->pitch_stream)[i];
+                    if (self->modebuffer[2] == 0)
+                        pos = PyFloat_AS_DOUBLE(self->pos);
+                    else
+                        pos = Stream_getData((Stream *)self->pos_stream)[i];
+                    if (self->modebuffer[3] == 0)
+                        dur = PyFloat_AS_DOUBLE(self->dur);
+                    else
+                        dur = Stream_getData((Stream *)self->dur_stream)[i];
+                    if (self->modebuffer[4] == 0)
+                        dev = PyFloat_AS_DOUBLE(self->dev);
+                    else
+                        dev = Stream_getData((Stream *)self->dev_stream)[i];
+                    if (self->modebuffer[5] == 0)
+                        pan = PyFloat_AS_DOUBLE(self->pan);
+                    else
+                        pan = Stream_getData((Stream *)self->pan_stream)[i];
+                    if (self->modebuffer[6] == 0)
+                        filterfreq = PyFloat_AS_DOUBLE(self->filterfreq);
+                    else
+                        filterfreq = Stream_getData((Stream *)self->filterfreq_stream)[i];
+                    if (self->modebuffer[7] == 0)
+                        filterq = PyFloat_AS_DOUBLE(self->filterq);
+                    else
+                        filterq = Stream_getData((Stream *)self->filterq_stream)[i];
+                    if (self->modebuffer[8] == 0)
+                        filtertype = PyFloat_AS_DOUBLE(self->filtertype);
+                    else
+                        filtertype = Stream_getData((Stream *)self->filtertype_stream)[i];
+                    if (pit < 0.0)
+                        pit = -pit;
+                    if (pos < 0.0)
+                        pos = 0.0;
+                    else if (pos >= size)
+                        pos = (MYFLT)size;
+                    if (dur < 0.0001)
+                        dur = 0.0001;
+                    if (dev < 0.0)
+                        dev = 0.0;
+                    else if (dev > 1.0)
+                        dev = 1.0;
+                    if (pan < 0.0)
+                        pan = 0.0;
+                    else if (pan > 1.0)
+                        pan = 1.0;
+                    if (filterfreq < 1.0)
+                        filterfreq = 1.0;
+                    else if (filterfreq > self->nyquist)
+                        filterfreq = self->nyquist;
+                    if (filterq < 0.1)
+                        filterq = 0.1;
+                    if (filtertype < 0)
+                        filtertype = 0;
+                    else if (filtertype > 4)
+                        filtertype = 4;
+                    filtertype = MYROUND(filtertype);
+                    self->gpos[j] = pos;
+                    self->glen[j] = dur * self->sr * pit * self->srScale;
+                    if ((pos + self->glen[j]) >= size || (pos + self->glen[j]) < 0)
+                        self->flags[j] = 0;
+                    self->phase[j] = 0.0;
+                    self->inc[j] = 1.0 / (dur * self->sr);
+                    self->devFactor = (RANDOM_UNIFORM * 2.0 - 1.0) * dev + 1.0;
+                    if (self->chnls == 2) {
+                        self->k1[j] = 0;
+                        self->k2[j] = self->bufsize;
+                        self->amp1[j] = MYSQRT(1.0 - pan);
+                        self->amp2[j] = MYSQRT(pan);
+                    }
+                    else {
+                        self->amp1[j] = MYSQRT(1.0 - pan);
+                        self->amp2[j] = MYSQRT(pan);
+                        min = 0;
+                        self->k1[j] = 0;
+                        self->k2[j] = self->bufsize;
+                        for (l=self->chnls; l>0; l--) {
+                            l1 = l - 1;
+                            min = l1 / (MYFLT)self->chnls;
+                            if (pan > min) {
+                                self->k1[j] = l1 * self->bufsize;
+                                if (l == self->chnls)
+                                    self->k2[j] = 0;
+                                else
+                                    self->k2[j] = l * self->bufsize;
+                                break;
+                            }
+                        }
+                    }
+                    if (filtertype != self->last_type[j] || filterfreq != self->last_freq[j] || filterq != self->last_q[j]) {
+                        self->last_freq[j] = filterfreq;
+                        self->last_q[j] = filterq;
+                        self->last_type[j] = filtertype;
+                        MainParticle2_compute_variables(self, filterfreq, filterq, j);
+                        self->qcomp[j] = 1.0;
+                        self->b0[j] = self->b1[j] = self->b2[j] = self->a0[j] = self->a1[j] = self->a2[j] = 0.0;
+                        if (filtertype == 0)
+                            MainParticle2_compute_coeffs_lp(self, j);
+                        else if (filtertype == 1)
+                            MainParticle2_compute_coeffs_hp(self, j);
+                        else if (filtertype == 2) {
+                            MainParticle2_compute_coeffs_bp(self, j);
+                            filterq = filterq < 10.0 ? filterq : 10.0;
+                            self->qcomp[j] = MYPOW(10, (filterq - 1) * 0.1);
+                        }
+                        else if (filtertype == 3)
+                            MainParticle2_compute_coeffs_bs(self, j);
+                        else if (filtertype == 4)
+                            MainParticle2_compute_coeffs_ap(self, j);
+                    }
+                    break;
+                }
+            }
+        }
+
+        /* compute active grains */
+        for (j=0; j<self->num; j++) {
+            if (self->flags[j]) {
+                phase = self->phase[j];
+                /* compute envelope */
+                index = phase * envsize;
+                ipart = (int)index;
+                amp = envlist[ipart] + (envlist[ipart+1] - envlist[ipart]) * (index - ipart);
+                /* compute sampling */
+                index = phase * self->glen[j] + self->gpos[j];
+                ipart = (int)index;
+                val = (tablelist[ipart] + (tablelist[ipart+1] - tablelist[ipart]) * (index - ipart));
+                /* filtering */
+                fval = ( (self->b0[j] * val) + (self->b1[j] * self->x1[j]) + (self->b2[j] * self->x2[j]) - (self->a1[j] * self->y1[j]) - (self->a2[j] * self->y2[j]) ) * self->a0[j];
+                self->y2[j] = self->y1[j];
+                self->y1[j] = fval;
+                self->x2[j] = self->x1[j];
+                self->x1[j] = val;
+                fval *= self->qcomp[j];
+                /* Add to output streams */
+                fval *= amp;
+                self->buffer_streams[i+self->k1[j]] += fval * self->amp1[j];
+                self->buffer_streams[i+self->k2[j]] += fval * self->amp2[j];
+                phase += self->inc[j];
+                if (phase >= 1.0)
+                    self->flags[j] = 0;
+                else
+                    self->phase[j] = phase;
+            }
+        }
+        flag = 0;
+    }
+}
+
+static void
+MainParticle2_setProcMode(MainParticle2 *self)
+{
+    int procmode = self->modebuffer[0];
+
+	switch (procmode) {
+        case 0:
+            if (self->chnls == 1)
+                self->proc_func_ptr = MainParticle2_transform_mono_i;
+            else
+                self->proc_func_ptr = MainParticle2_transform_i;
+            break;
+        case 1:
+            if (self->chnls == 1)
+                self->proc_func_ptr = MainParticle2_transform_mono_a;
+            else
+                self->proc_func_ptr = MainParticle2_transform_a;
+            break;
+    }
+}
+
+static void
+MainParticle2_compute_next_data_frame(MainParticle2 *self)
+{
+    (*self->proc_func_ptr)(self);
+}
+
+static int
+MainParticle2_traverse(MainParticle2 *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->table);
+    Py_VISIT(self->env);
+    Py_VISIT(self->dens);
+    Py_VISIT(self->dens_stream);
+    Py_VISIT(self->pitch);
+    Py_VISIT(self->pitch_stream);
+    Py_VISIT(self->pos);
+    Py_VISIT(self->pos_stream);
+    Py_VISIT(self->dur);
+    Py_VISIT(self->dur_stream);
+    Py_VISIT(self->dev);
+    Py_VISIT(self->dev_stream);
+    Py_VISIT(self->pan);
+    Py_VISIT(self->pan_stream);
+    Py_VISIT(self->filterfreq);
+    Py_VISIT(self->filterfreq_stream);
+    Py_VISIT(self->filterq);
+    Py_VISIT(self->filterq_stream);
+    Py_VISIT(self->filtertype);
+    Py_VISIT(self->filtertype_stream);
+    return 0;
+}
+
+static int
+MainParticle2_clear(MainParticle2 *self)
+{
+    pyo_CLEAR
+    Py_CLEAR(self->table);
+    Py_CLEAR(self->env);
+    Py_CLEAR(self->dens);
+    Py_CLEAR(self->dens_stream);
+    Py_CLEAR(self->pitch);
+    Py_CLEAR(self->pitch_stream);
+    Py_CLEAR(self->pos);
+    Py_CLEAR(self->pos_stream);
+    Py_CLEAR(self->dur);
+    Py_CLEAR(self->dur_stream);
+    Py_CLEAR(self->dev);
+    Py_CLEAR(self->dev_stream);
+    Py_CLEAR(self->pan);
+    Py_CLEAR(self->pan_stream);
+    Py_CLEAR(self->filterfreq);
+    Py_CLEAR(self->filterfreq_stream);
+    Py_CLEAR(self->filterq);
+    Py_CLEAR(self->filterq_stream);
+    Py_CLEAR(self->filtertype);
+    Py_CLEAR(self->filtertype_stream);
+    return 0;
+}
+
+static void
+MainParticle2_dealloc(MainParticle2* self)
+{
+    pyo_DEALLOC
+    free(self->gpos);
+    free(self->glen);
+    free(self->inc);
+    free(self->flags);
+    free(self->k1);
+    free(self->k2);
+    free(self->phase);
+    free(self->amp1);
+    free(self->amp2);
+    free(self->last_freq);
+    free(self->last_q);
+    free(self->last_type);
+    free(self->x1);
+    free(self->x2);
+    free(self->y1);
+    free(self->y2);
+    free(self->c);
+    free(self->w0);
+    free(self->alpha);
+    free(self->qcomp);
+    free(self->b0);
+    free(self->b1);
+    free(self->b2);
+    free(self->a0);
+    free(self->a1);
+    free(self->a2);
+    free(self->buffer_streams);
+    MainParticle2_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+MYFLT *
+MainParticle2_getSamplesBuffer(MainParticle2 *self)
+{
+    return (MYFLT *)self->buffer_streams;
+}
+
+static PyObject *
+MainParticle2_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i;
+    PyObject *tabletmp, *envtmp, *denstmp=NULL, *pitchtmp=NULL, *postmp=NULL, *durtmp=NULL;
+    PyObject *devtmp=NULL, *pantmp=NULL, *filterfreqtmp=NULL, *filterqtmp=NULL, *filtertypetmp=NULL;
+    MainParticle2 *self;
+    self = (MainParticle2 *)type->tp_alloc(type, 0);
+
+    self->dens = PyFloat_FromDouble(50);
+    self->pitch = PyFloat_FromDouble(1);
+    self->pos = PyFloat_FromDouble(0.0);
+    self->dur = PyFloat_FromDouble(0.1);
+    self->dev = PyFloat_FromDouble(0);
+    self->pan = PyFloat_FromDouble(0.5);
+    self->filterq = PyFloat_FromDouble(0.7);
+    self->filtertype = PyFloat_FromDouble(0);
+    self->timer = self->devFactor = 1.0;
+    self->srScale = 1.0;
+    self->num = 0;
+    self->chnls = 1;
+	self->modebuffer[0] = 0;
+	self->modebuffer[1] = 0;
+	self->modebuffer[2] = 0;
+	self->modebuffer[3] = 0;
+	self->modebuffer[4] = 0;
+	self->modebuffer[5] = 0;
+	self->modebuffer[6] = 0;
+	self->modebuffer[7] = 0;
+	self->modebuffer[8] = 0;
+
+    INIT_OBJECT_COMMON
+
+    self->oneOnSr = 1.0 / self->sr;
+    self->srOnRandMax = self->sr / (MYFLT)PYO_RAND_MAX;
+    self->nyquist = (MYFLT)self->sr * 0.49;
+    self->twopiOverSr = TWOPI / (MYFLT)self->sr;
+
+    self->filterfreq = PyFloat_FromDouble(self->nyquist);
+
+    Stream_setFunctionPtr(self->stream, MainParticle2_compute_next_data_frame);
+    self->mode_func_ptr = MainParticle2_setProcMode;
+
+    static char *kwlist[] = {"table", "env", "dens", "pitch", "pos", "dur", "dev", "pan", "filterfreq", "filterq", "filtertype", "chnls", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OOOOOOOOOi", kwlist, &tabletmp, &envtmp, &denstmp, &pitchtmp, &postmp, &durtmp, &devtmp, &pantmp, &filterfreqtmp, &filterqtmp, &filtertypetmp, &self->chnls))
+        Py_RETURN_NONE;
+
+    if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) {
+        PyErr_SetString(PyExc_TypeError, "\"table\" argument of MainParticle2 must be a PyoTableObject.\n");
+        Py_RETURN_NONE;
+    }
+    Py_XDECREF(self->table);
+    self->table = PyObject_CallMethod((PyObject *)tabletmp, "getTableStream", "");
+    self->srScale = TableStream_getSamplingRate(self->table) / self->sr;
+
+    if ( PyObject_HasAttrString((PyObject *)envtmp, "getTableStream") == 0 ) {
+        PyErr_SetString(PyExc_TypeError, "\"env\" argument of MainParticle2 must be a PyoTableObject.\n");
+        Py_RETURN_NONE;
+    }
+    Py_XDECREF(self->env);
+    self->env = PyObject_CallMethod((PyObject *)envtmp, "getTableStream", "");
+
+    if (denstmp) {
+        PyObject_CallMethod((PyObject *)self, "setDens", "O", denstmp);
+    }
+
+    if (pitchtmp) {
+        PyObject_CallMethod((PyObject *)self, "setPitch", "O", pitchtmp);
+    }
+
+    if (postmp) {
+        PyObject_CallMethod((PyObject *)self, "setPos", "O", postmp);
+    }
+
+    if (durtmp) {
+        PyObject_CallMethod((PyObject *)self, "setDur", "O", durtmp);
+    }
+
+    if (devtmp) {
+        PyObject_CallMethod((PyObject *)self, "setDev", "O", devtmp);
+    }
+
+    if (pantmp) {
+        PyObject_CallMethod((PyObject *)self, "setPan", "O", pantmp);
+    }
+
+    if (filterfreqtmp) {
+        PyObject_CallMethod((PyObject *)self, "setFilterfreq", "O", filterfreqtmp);
+    }
+
+    if (filterqtmp) {
+        PyObject_CallMethod((PyObject *)self, "setFilterq", "O", filterqtmp);
+    }
+
+    if (filtertypetmp) {
+        PyObject_CallMethod((PyObject *)self, "setFiltertype", "O", filtertypetmp);
+    }
+
+    PyObject_CallMethod(self->server, "addStream", "O", self->stream);
+
+    if (self->chnls < 1)
+        self->chnls = 1;
+
+    self->gpos = (MYFLT *)realloc(self->gpos, MAINPARTICLE_MAX_GRAINS * sizeof(MYFLT));
+    self->glen = (MYFLT *)realloc(self->glen, MAINPARTICLE_MAX_GRAINS * sizeof(MYFLT));
+    self->inc = (MYFLT *)realloc(self->inc, MAINPARTICLE_MAX_GRAINS * sizeof(MYFLT));
+    self->phase = (MYFLT *)realloc(self->phase, MAINPARTICLE_MAX_GRAINS * sizeof(MYFLT));
+    self->amp1 = (MYFLT *)realloc(self->amp1, MAINPARTICLE_MAX_GRAINS * sizeof(MYFLT));
+    self->amp2 = (MYFLT *)realloc(self->amp2, MAINPARTICLE_MAX_GRAINS * sizeof(MYFLT));
+    self->flags = (int *)realloc(self->flags, MAINPARTICLE_MAX_GRAINS * sizeof(int));
+    self->k1 = (int *)realloc(self->k1, MAINPARTICLE_MAX_GRAINS * sizeof(int));
+    self->k2 = (int *)realloc(self->k2, MAINPARTICLE_MAX_GRAINS * sizeof(int));
+    self->last_freq = (MYFLT *)realloc(self->last_freq, MAINPARTICLE_MAX_GRAINS * sizeof(MYFLT));
+    self->last_q = (MYFLT *)realloc(self->last_q, MAINPARTICLE_MAX_GRAINS * sizeof(MYFLT));
+    self->last_type = (MYFLT *)realloc(self->last_type, MAINPARTICLE_MAX_GRAINS * sizeof(MYFLT));
+    self->x1 = (MYFLT *)realloc(self->x1, MAINPARTICLE_MAX_GRAINS * sizeof(MYFLT));
+    self->x2 = (MYFLT *)realloc(self->x2, MAINPARTICLE_MAX_GRAINS * sizeof(MYFLT));
+    self->y1 = (MYFLT *)realloc(self->y1, MAINPARTICLE_MAX_GRAINS * sizeof(MYFLT));
+    self->y2 = (MYFLT *)realloc(self->y2, MAINPARTICLE_MAX_GRAINS * sizeof(MYFLT));
+    self->c = (MYFLT *)realloc(self->c, MAINPARTICLE_MAX_GRAINS * sizeof(MYFLT));
+    self->w0 = (MYFLT *)realloc(self->w0, MAINPARTICLE_MAX_GRAINS * sizeof(MYFLT));
+    self->alpha = (MYFLT *)realloc(self->alpha, MAINPARTICLE_MAX_GRAINS * sizeof(MYFLT));
+    self->qcomp = (MYFLT *)realloc(self->qcomp, MAINPARTICLE_MAX_GRAINS * sizeof(MYFLT));
+    self->b0 = (MYFLT *)realloc(self->b0, MAINPARTICLE_MAX_GRAINS * sizeof(MYFLT));
+    self->b1 = (MYFLT *)realloc(self->b1, MAINPARTICLE_MAX_GRAINS * sizeof(MYFLT));
+    self->b2 = (MYFLT *)realloc(self->b2, MAINPARTICLE_MAX_GRAINS * sizeof(MYFLT));
+    self->a0 = (MYFLT *)realloc(self->a0, MAINPARTICLE_MAX_GRAINS * sizeof(MYFLT));
+    self->a1 = (MYFLT *)realloc(self->a1, MAINPARTICLE_MAX_GRAINS * sizeof(MYFLT));
+    self->a2 = (MYFLT *)realloc(self->a2, MAINPARTICLE_MAX_GRAINS * sizeof(MYFLT));
+
+    for (i=0; i<MAINPARTICLE_MAX_GRAINS; i++) {
+        self->gpos[i] = self->glen[i] = self->inc[i] = self->phase[i] = self->amp1[i] = self->amp2[i] = 0.0;
+        self->last_freq[i] = self->last_q[i] = self->x1[i] = self->x2[i] = self->y1[i] = self->y2[i] = 0.0;
+        self->last_type[i] = -1.0;
+        self->qcomp[i] = 1.0;
+        self->c[i] = self->w0[i] = self->alpha[i] = self->b0[i] = self->b1[i] = self->b2[i] = self->a0[i] = self->a1[i] = self->a2[i] = 0.0;
+        self->flags[i] = self->k1[i] = self->k2[i] = 0;
+    }
+
+    self->buffer_streams = (MYFLT *)realloc(self->buffer_streams, self->bufsize * self->chnls * sizeof(MYFLT));
+    for (i=0; i<self->bufsize*self->chnls; i++) {
+        self->buffer_streams[i] = 0.0;
+    }
+
+    Server_generateSeed((Server *)self->server, MAINPARTICLE_ID);
+
+    (*self->mode_func_ptr)(self);
+
+    return (PyObject *)self;
+}
+
+static PyObject * MainParticle2_getServer(MainParticle2* self) { GET_SERVER };
+static PyObject * MainParticle2_getStream(MainParticle2* self) { GET_STREAM };
+
+static PyObject * MainParticle2_play(MainParticle2 *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * MainParticle2_stop(MainParticle2 *self) { STOP };
+
+static PyObject *
+MainParticle2_setDens(MainParticle2 *self, PyObject *arg)
+{
+	PyObject *tmp, *streamtmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	tmp = arg;
+	Py_INCREF(tmp);
+	Py_DECREF(self->dens);
+	if (isNumber == 1) {
+		self->dens = PyNumber_Float(tmp);
+        self->modebuffer[0] = 0;
+	}
+	else {
+		self->dens = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->dens, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->dens_stream);
+        self->dens_stream = (Stream *)streamtmp;
+		self->modebuffer[0] = 1;
+	}
+
+    (*self->mode_func_ptr)(self);
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+MainParticle2_setPitch(MainParticle2 *self, PyObject *arg)
+{
+	PyObject *tmp, *streamtmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	tmp = arg;
+	Py_INCREF(tmp);
+	Py_DECREF(self->pitch);
+	if (isNumber == 1) {
+		self->pitch = PyNumber_Float(tmp);
+        self->modebuffer[1] = 0;
+	}
+	else {
+		self->pitch = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->pitch, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->pitch_stream);
+        self->pitch_stream = (Stream *)streamtmp;
+		self->modebuffer[1] = 1;
+	}
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+MainParticle2_setPos(MainParticle2 *self, PyObject *arg)
+{
+	PyObject *tmp, *streamtmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	tmp = arg;
+	Py_INCREF(tmp);
+	Py_DECREF(self->pos);
+	if (isNumber == 1) {
+		self->pos = PyNumber_Float(tmp);
+        self->modebuffer[2] = 0;
+	}
+	else {
+		self->pos = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->pos, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->pos_stream);
+        self->pos_stream = (Stream *)streamtmp;
+		self->modebuffer[2] = 1;
+	}
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+MainParticle2_setDur(MainParticle2 *self, PyObject *arg)
+{
+	PyObject *tmp, *streamtmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	tmp = arg;
+	Py_INCREF(tmp);
+	Py_DECREF(self->dur);
+	if (isNumber == 1) {
+		self->dur = PyNumber_Float(tmp);
+        self->modebuffer[3] = 0;
+	}
+	else {
+		self->dur = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->dur, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->dur_stream);
+        self->dur_stream = (Stream *)streamtmp;
+		self->modebuffer[3] = 1;
+	}
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+MainParticle2_setDev(MainParticle2 *self, PyObject *arg)
+{
+	PyObject *tmp, *streamtmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	tmp = arg;
+	Py_INCREF(tmp);
+	Py_DECREF(self->dev);
+	if (isNumber == 1) {
+		self->dev = PyNumber_Float(tmp);
+        self->modebuffer[4] = 0;
+	}
+	else {
+		self->dev = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->dev, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->dev_stream);
+        self->dev_stream = (Stream *)streamtmp;
+		self->modebuffer[4] = 1;
+	}
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+MainParticle2_setPan(MainParticle2 *self, PyObject *arg)
+{
+	PyObject *tmp, *streamtmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	tmp = arg;
+	Py_INCREF(tmp);
+	Py_DECREF(self->pan);
+	if (isNumber == 1) {
+		self->pan = PyNumber_Float(tmp);
+        self->modebuffer[5] = 0;
+	}
+	else {
+		self->pan = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->pan, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->pan_stream);
+        self->pan_stream = (Stream *)streamtmp;
+		self->modebuffer[5] = 1;
+	}
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+MainParticle2_setFilterfreq(MainParticle2 *self, PyObject *arg)
+{
+	PyObject *tmp, *streamtmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	tmp = arg;
+	Py_INCREF(tmp);
+	Py_DECREF(self->filterfreq);
+	if (isNumber == 1) {
+		self->filterfreq = PyNumber_Float(tmp);
+        self->modebuffer[6] = 0;
+	}
+	else {
+		self->filterfreq = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->filterfreq, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->filterfreq_stream);
+        self->filterfreq_stream = (Stream *)streamtmp;
+		self->modebuffer[6] = 1;
+	}
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+MainParticle2_setFilterq(MainParticle2 *self, PyObject *arg)
+{
+	PyObject *tmp, *streamtmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	tmp = arg;
+	Py_INCREF(tmp);
+	Py_DECREF(self->filterq);
+	if (isNumber == 1) {
+		self->filterq = PyNumber_Float(tmp);
+        self->modebuffer[7] = 0;
+	}
+	else {
+		self->filterq = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->filterq, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->filterq_stream);
+        self->filterq_stream = (Stream *)streamtmp;
+		self->modebuffer[7] = 1;
+	}
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+MainParticle2_setFiltertype(MainParticle2 *self, PyObject *arg)
+{
+	PyObject *tmp, *streamtmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	tmp = arg;
+	Py_INCREF(tmp);
+	Py_DECREF(self->filtertype);
+	if (isNumber == 1) {
+		self->filtertype = PyNumber_Float(tmp);
+        self->modebuffer[8] = 0;
+	}
+	else {
+		self->filtertype = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->filtertype, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->filtertype_stream);
+        self->filtertype_stream = (Stream *)streamtmp;
+		self->modebuffer[8] = 1;
+	}
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+MainParticle2_getTable(MainParticle2* self)
+{
+    Py_INCREF(self->table);
+    return self->table;
+};
+
+static PyObject *
+MainParticle2_setTable(MainParticle2 *self, PyObject *arg)
+{
+	PyObject *tmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	tmp = arg;
+	Py_DECREF(self->table);
+    self->table = PyObject_CallMethod((PyObject *)tmp, "getTableStream", "");
+    self->srScale = TableStream_getSamplingRate(self->table) / self->sr;
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+MainParticle2_getEnv(MainParticle2* self)
+{
+    Py_INCREF(self->env);
+    return self->env;
+};
+
+static PyObject *
+MainParticle2_setEnv(MainParticle2 *self, PyObject *arg)
+{
+	PyObject *tmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	tmp = arg;
+	Py_DECREF(self->env);
+    self->env = PyObject_CallMethod((PyObject *)tmp, "getTableStream", "");
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyMemberDef MainParticle2_members[] = {
+    {"server", T_OBJECT_EX, offsetof(MainParticle2, server), 0, "Pyo server."},
+    {"stream", T_OBJECT_EX, offsetof(MainParticle2, stream), 0, "Stream object."},
+    {"table", T_OBJECT_EX, offsetof(MainParticle2, table), 0, "Sound table."},
+    {"env", T_OBJECT_EX, offsetof(MainParticle2, env), 0, "Envelope table."},
+    {"dens", T_OBJECT_EX, offsetof(MainParticle2, dens), 0, "Density of grains per second."},
+    {"pitch", T_OBJECT_EX, offsetof(MainParticle2, pitch), 0, "Speed of the reading pointer."},
+    {"pos", T_OBJECT_EX, offsetof(MainParticle2, pos), 0, "Position in the sound table."},
+    {"dur", T_OBJECT_EX, offsetof(MainParticle2, dur), 0, "Duration of each grains."},
+    {"dev", T_OBJECT_EX, offsetof(MainParticle2, dev), 0, "Grain start point deviation factor."},
+    {"pan", T_OBJECT_EX, offsetof(MainParticle2, pan), 0, "Grain panning factor."},
+    {"filterfreq", T_OBJECT_EX, offsetof(MainParticle2, filterfreq), 0, "Grain filter center/cutoff frequency."},
+    {"filterq", T_OBJECT_EX, offsetof(MainParticle2, filterq), 0, "Grain filter Q."},
+    {"filtertype", T_OBJECT_EX, offsetof(MainParticle2, filtertype), 0, "Grain filter type."},
+    {NULL}  /* Sentinel */
+};
+
+static PyMethodDef MainParticle2_methods[] = {
+    {"getTable", (PyCFunction)MainParticle2_getTable, METH_NOARGS, "Returns sound table object."},
+    {"setTable", (PyCFunction)MainParticle2_setTable, METH_O, "Sets sound table."},
+    {"getEnv", (PyCFunction)MainParticle2_getEnv, METH_NOARGS, "Returns envelope table object."},
+    {"setEnv", (PyCFunction)MainParticle2_setEnv, METH_O, "Sets envelope table."},
+    {"getServer", (PyCFunction)MainParticle2_getServer, METH_NOARGS, "Returns server object."},
+    {"_getStream", (PyCFunction)MainParticle2_getStream, METH_NOARGS, "Returns stream object."},
+    {"play", (PyCFunction)MainParticle2_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+    {"stop", (PyCFunction)MainParticle2_stop, METH_NOARGS, "Stops computing."},
+	{"setDens", (PyCFunction)MainParticle2_setDens, METH_O, "Sets the density of grains per second."},
+	{"setPitch", (PyCFunction)MainParticle2_setPitch, METH_O, "Sets global pitch factor."},
+    {"setPos", (PyCFunction)MainParticle2_setPos, METH_O, "Sets position in the sound table."},
+    {"setDur", (PyCFunction)MainParticle2_setDur, METH_O, "Sets the grain duration."},
+	{"setDev", (PyCFunction)MainParticle2_setDev, METH_O, "Sets grain start point deviation factor."},
+	{"setPan", (PyCFunction)MainParticle2_setPan, METH_O, "Sets grain panning factor."},
+	{"setFilterfreq", (PyCFunction)MainParticle2_setFilterfreq, METH_O, "Sets grain filter center/cutoff frequency."},
+	{"setFilterq", (PyCFunction)MainParticle2_setFilterq, METH_O, "Sets grain filter Q."},
+	{"setFiltertype", (PyCFunction)MainParticle2_setFiltertype, METH_O, "Sets grain filter type."},
+    {NULL}  /* Sentinel */
+};
+
+PyTypeObject MainParticle2Type = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "_pyo.MainParticle2_base",         /*tp_name*/
+    sizeof(MainParticle2),         /*tp_basicpitch*/
+    0,                         /*tp_itempitch*/
+    (destructor)MainParticle2_dealloc, /*tp_dealloc*/
+    0,                         /*tp_print*/
+    0,                         /*tp_getattr*/
+    0,                         /*tp_setattr*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
+    0,                         /*tp_repr*/
+    0,             /*tp_as_number*/
+    0,                         /*tp_as_sequence*/
+    0,                         /*tp_as_mapping*/
+    0,                         /*tp_hash */
+    0,                         /*tp_call*/
+    0,                         /*tp_str*/
+    0,                         /*tp_getattro*/
+    0,                         /*tp_setattro*/
+    0,                         /*tp_as_buffer*/
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
+    "MainParticle2 objects. Accumulation of multiples bandpass filtered grains of sound.",           /* tp_doc */
+    (traverseproc)MainParticle2_traverse,   /* tp_traverse */
+    (inquiry)MainParticle2_clear,           /* tp_clear */
+    0,		               /* tp_richcompare */
+    0,		               /* tp_weaklistoffset */
+    0,		               /* tp_iter */
+    0,		               /* tp_iternext */
+    MainParticle2_methods,             /* tp_methods */
+    MainParticle2_members,             /* tp_members */
+    0,                      /* tp_getset */
+    0,                         /* tp_base */
+    0,                         /* tp_dict */
+    0,                         /* tp_descr_get */
+    0,                         /* tp_descr_set */
+    0,                         /* tp_dictoffset */
+    0,      /* tp_init */
+    0,                         /* tp_alloc */
+    MainParticle2_new,                 /* tp_new */
+};
+
+typedef struct {
+    pyo_audio_HEAD
+    MainParticle2 *mainSplitter;
+    int modebuffer[2];
+    int chnl; // panning order
+} Particle2;
+
+static void Particle2_postprocessing_ii(Particle2 *self) { POST_PROCESSING_II };
+static void Particle2_postprocessing_ai(Particle2 *self) { POST_PROCESSING_AI };
+static void Particle2_postprocessing_ia(Particle2 *self) { POST_PROCESSING_IA };
+static void Particle2_postprocessing_aa(Particle2 *self) { POST_PROCESSING_AA };
+static void Particle2_postprocessing_ireva(Particle2 *self) { POST_PROCESSING_IREVA };
+static void Particle2_postprocessing_areva(Particle2 *self) { POST_PROCESSING_AREVA };
+static void Particle2_postprocessing_revai(Particle2 *self) { POST_PROCESSING_REVAI };
+static void Particle2_postprocessing_revaa(Particle2 *self) { POST_PROCESSING_REVAA };
+static void Particle2_postprocessing_revareva(Particle2 *self) { POST_PROCESSING_REVAREVA };
+
+static void
+Particle2_setProcMode(Particle2 *self)
+{
+    int muladdmode;
+    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
+
+	switch (muladdmode) {
+        case 0:
+            self->muladd_func_ptr = Particle2_postprocessing_ii;
+            break;
+        case 1:
+            self->muladd_func_ptr = Particle2_postprocessing_ai;
+            break;
+        case 2:
+            self->muladd_func_ptr = Particle2_postprocessing_revai;
+            break;
+        case 10:
+            self->muladd_func_ptr = Particle2_postprocessing_ia;
+            break;
+        case 11:
+            self->muladd_func_ptr = Particle2_postprocessing_aa;
+            break;
+        case 12:
+            self->muladd_func_ptr = Particle2_postprocessing_revaa;
+            break;
+        case 20:
+            self->muladd_func_ptr = Particle2_postprocessing_ireva;
+            break;
+        case 21:
+            self->muladd_func_ptr = Particle2_postprocessing_areva;
+            break;
+        case 22:
+            self->muladd_func_ptr = Particle2_postprocessing_revareva;
+            break;
+    }
+}
+
+static void
+Particle2_compute_next_data_frame(Particle2 *self)
+{
+    int i;
+    MYFLT *tmp;
+    int offset = self->chnl * self->bufsize;
+    tmp = MainParticle2_getSamplesBuffer((MainParticle2 *)self->mainSplitter);
+    for (i=0; i<self->bufsize; i++) {
+        self->data[i] = tmp[i + offset];
+    }
+    (*self->muladd_func_ptr)(self);
+}
+
+static int
+Particle2_traverse(Particle2 *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->mainSplitter);
+    return 0;
+}
+
+static int
+Particle2_clear(Particle2 *self)
+{
+    pyo_CLEAR
+    Py_CLEAR(self->mainSplitter);
+    return 0;
+}
+
+static void
+Particle2_dealloc(Particle2* self)
+{
+    pyo_DEALLOC
+    Particle2_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+Particle2_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i;
+    PyObject *maintmp=NULL, *multmp=NULL, *addtmp=NULL;
+    Particle2 *self;
+    self = (Particle2 *)type->tp_alloc(type, 0);
+
+	self->modebuffer[0] = 0;
+	self->modebuffer[1] = 0;
+
+    INIT_OBJECT_COMMON
+    Stream_setFunctionPtr(self->stream, Particle2_compute_next_data_frame);
+    self->mode_func_ptr = Particle2_setProcMode;
+
+    static char *kwlist[] = {"mainSplitter", "chnl", "mul", "add", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "Oi|OO", kwlist, &maintmp, &self->chnl, &multmp, &addtmp))
+        Py_RETURN_NONE;
+
+    Py_XDECREF(self->mainSplitter);
+    Py_INCREF(maintmp);
+    self->mainSplitter = (MainParticle2 *)maintmp;
+
+    if (multmp) {
+        PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp);
+    }
+
+    if (addtmp) {
+        PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp);
+    }
+
+    PyObject_CallMethod(self->server, "addStream", "O", self->stream);
+
+    (*self->mode_func_ptr)(self);
+
+    return (PyObject *)self;
+}
+
+static PyObject * Particle2_getServer(Particle2* self) { GET_SERVER };
+static PyObject * Particle2_getStream(Particle2* self) { GET_STREAM };
+static PyObject * Particle2_setMul(Particle2 *self, PyObject *arg) { SET_MUL };
+static PyObject * Particle2_setAdd(Particle2 *self, PyObject *arg) { SET_ADD };
+static PyObject * Particle2_setSub(Particle2 *self, PyObject *arg) { SET_SUB };
+static PyObject * Particle2_setDiv(Particle2 *self, PyObject *arg) { SET_DIV };
+
+static PyObject * Particle2_play(Particle2 *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * Particle2_out(Particle2 *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * Particle2_stop(Particle2 *self) { STOP };
+
+static PyObject * Particle2_multiply(Particle2 *self, PyObject *arg) { MULTIPLY };
+static PyObject * Particle2_inplace_multiply(Particle2 *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * Particle2_add(Particle2 *self, PyObject *arg) { ADD };
+static PyObject * Particle2_inplace_add(Particle2 *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * Particle2_sub(Particle2 *self, PyObject *arg) { SUB };
+static PyObject * Particle2_inplace_sub(Particle2 *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * Particle2_div(Particle2 *self, PyObject *arg) { DIV };
+static PyObject * Particle2_inplace_div(Particle2 *self, PyObject *arg) { INPLACE_DIV };
+
+static PyMemberDef Particle2_members[] = {
+{"server", T_OBJECT_EX, offsetof(Particle2, server), 0, "Pyo server."},
+{"stream", T_OBJECT_EX, offsetof(Particle2, stream), 0, "Stream object."},
+{"mul", T_OBJECT_EX, offsetof(Particle2, mul), 0, "Mul factor."},
+{"add", T_OBJECT_EX, offsetof(Particle2, add), 0, "Add factor."},
+{NULL}  /* Sentinel */
+};
+
+static PyMethodDef Particle2_methods[] = {
+{"getServer", (PyCFunction)Particle2_getServer, METH_NOARGS, "Returns server object."},
+{"_getStream", (PyCFunction)Particle2_getStream, METH_NOARGS, "Returns stream object."},
+{"play", (PyCFunction)Particle2_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+{"out", (PyCFunction)Particle2_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+{"stop", (PyCFunction)Particle2_stop, METH_NOARGS, "Stops computing."},
+{"setMul", (PyCFunction)Particle2_setMul, METH_O, "Sets Particle2 mul factor."},
+{"setAdd", (PyCFunction)Particle2_setAdd, METH_O, "Sets Particle2 add factor."},
+{"setSub", (PyCFunction)Particle2_setSub, METH_O, "Sets inverse add factor."},
+{"setDiv", (PyCFunction)Particle2_setDiv, METH_O, "Sets inverse mul factor."},
+{NULL}  /* Sentinel */
+};
+
+static PyNumberMethods Particle2_as_number = {
+(binaryfunc)Particle2_add,                      /*nb_add*/
+(binaryfunc)Particle2_sub,                 /*nb_subtract*/
+(binaryfunc)Particle2_multiply,                 /*nb_multiply*/
+INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
+0,                /*nb_remainder*/
+0,                   /*nb_divmod*/
+0,                   /*nb_power*/
+0,                  /*nb_neg*/
+0,                /*nb_pos*/
+0,                  /*(unaryfunc)array_abs,*/
+0,                    /*nb_nonzero*/
+0,                    /*nb_invert*/
+0,               /*nb_lshift*/
+0,              /*nb_rshift*/
+0,              /*nb_and*/
+0,              /*nb_xor*/
+0,               /*nb_or*/
+INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
+0,                       /*nb_int*/
+0,                      /*nb_long*/
+0,                     /*nb_float*/
+INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
+(binaryfunc)Particle2_inplace_add,              /*inplace_add*/
+(binaryfunc)Particle2_inplace_sub,         /*inplace_subtract*/
+(binaryfunc)Particle2_inplace_multiply,         /*inplace_multiply*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
+0,        /*inplace_remainder*/
+0,           /*inplace_power*/
+0,       /*inplace_lshift*/
+0,      /*inplace_rshift*/
+0,      /*inplace_and*/
+0,      /*inplace_xor*/
+0,       /*inplace_or*/
+0,             /*nb_floor_divide*/
+(binaryfunc)Particle2_div,                       /*nb_true_divide*/
+0,     /*nb_inplace_floor_divide*/
+(binaryfunc)Particle2_inplace_div,                       /*nb_inplace_true_divide*/
+0,                     /* nb_index */
+};
+
+PyTypeObject Particle2Type = {
+PyVarObject_HEAD_INIT(NULL, 0)
+"_pyo.Particle2_base",         /*tp_name*/
+sizeof(Particle2),         /*tp_basicsize*/
+0,                         /*tp_itemsize*/
+(destructor)Particle2_dealloc, /*tp_dealloc*/
+0,                         /*tp_print*/
+0,                         /*tp_getattr*/
+0,                         /*tp_setattr*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
+0,                         /*tp_repr*/
+&Particle2_as_number,             /*tp_as_number*/
+0,                         /*tp_as_sequence*/
+0,                         /*tp_as_mapping*/
+0,                         /*tp_hash */
+0,                         /*tp_call*/
+0,                         /*tp_str*/
+0,                         /*tp_getattro*/
+0,                         /*tp_setattro*/
+0,                         /*tp_as_buffer*/
+Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES,  /*tp_flags*/
+"Particle2 objects. Reads one band from a MainParticle2 object.",           /* tp_doc */
+(traverseproc)Particle2_traverse,   /* tp_traverse */
+(inquiry)Particle2_clear,           /* tp_clear */
+0,		               /* tp_richcompare */
+0,		               /* tp_weaklistoffset */
+0,		               /* tp_iter */
+0,		               /* tp_iternext */
+Particle2_methods,             /* tp_methods */
+Particle2_members,             /* tp_members */
+0,                      /* tp_getset */
+0,                         /* tp_base */
+0,                         /* tp_dict */
+0,                         /* tp_descr_get */
+0,                         /* tp_descr_set */
+0,                         /* tp_dictoffset */
+0,      /* tp_init */
+0,                         /* tp_alloc */
+Particle2_new,                 /* tp_new */
 };
\ No newline at end of file
diff --git a/src/objects/matrixmodule.c b/src/objects/matrixmodule.c
index a5d375b..38f0d28 100644
--- a/src/objects/matrixmodule.c
+++ b/src/objects/matrixmodule.c
@@ -604,7 +604,6 @@ MatrixRec_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     INIT_OBJECT_COMMON
 
     Stream_setFunctionPtr(self->stream, MatrixRec_compute_next_data_frame);
-    Stream_setStreamActive(self->stream, 0);
 
     static char *kwlist[] = {"input", "matrix", "fadetime", "delay", NULL};
 
diff --git a/src/objects/metromodule.c b/src/objects/metromodule.c
index 1262243..adff001 100644
--- a/src/objects/metromodule.c
+++ b/src/objects/metromodule.c
@@ -389,16 +389,16 @@ typedef struct {
     int modebuffer[1];
     double sampleToSec;
     double currentTime;
-    double duration;
-    int *seq;
-    int count;
+    double *seq;
+    double when;
     MYFLT *buffer_streams;
     int seqsize;
     int poly;
-    int flag;
     int tap;
     int voiceCount;
     int newseq;
+    int onlyonce;
+    int to_stop;
 } Seqer;
 
 static void
@@ -407,9 +407,9 @@ Seqer_reset(Seqer *self)
     int i;
 
     self->seqsize = PyList_Size(self->tmp);
-    self->seq = (int *)realloc(self->seq, self->seqsize * sizeof(int));
+    self->seq = (double *)realloc(self->seq, self->seqsize * sizeof(double));
     for (i=0; i<self->seqsize; i++) {
-        self->seq[i] = PyInt_AS_LONG(PyNumber_Int(PyList_GET_ITEM(self->tmp, i)));
+        self->seq[i] = PyFloat_AsDouble(PyList_GET_ITEM(self->tmp, i));
     }
     self->newseq = 0;
 }
@@ -421,30 +421,33 @@ Seqer_generate_i(Seqer *self) {
 
     tm = PyFloat_AS_DOUBLE(self->time);
 
-    if (self->currentTime == -1.0) {
-        self->currentTime = tm;
-    }
-
     for (i=0; i<(self->poly*self->bufsize); i++) {
         self->buffer_streams[i] = 0.0;
     }
 
+    if (self->to_stop) {
+        PyObject_CallMethod((PyObject *)self, "stop", NULL);
+        self->to_stop = 0;
+        return;
+    }
+
     for (i=0; i<self->bufsize; i++) {
         self->currentTime += self->sampleToSec;
-        if (self->currentTime >= tm) {
-            self->currentTime -= tm;
-            self->count++;
-            if (self->count >= self->seq[self->tap]) {
-                self->count = 0;
-                self->buffer_streams[i + self->voiceCount * self->bufsize] = 1.0;
-                self->voiceCount++;
-                if (self->voiceCount >= self->poly)
-                    self->voiceCount = 0;
-                self->tap++;
-                if (self->tap >= self->seqsize) {
-                    self->tap = 0;
-                    if (self->newseq == 1)
-                        Seqer_reset(self);
+        if (self->currentTime >= self->when) {
+            self->currentTime -= self->when;
+            self->when = self->seq[self->tap] * tm;
+            self->buffer_streams[i + self->voiceCount * self->bufsize] = 1.0;
+            self->voiceCount++;
+            if (self->voiceCount >= self->poly)
+                self->voiceCount = 0;
+            self->tap++;
+            if (self->tap >= self->seqsize) {
+                self->tap = 0;
+                if (self->newseq == 1)
+                    Seqer_reset(self);
+                if (self->onlyonce) {
+                    self->to_stop = 1;
+                    return;
                 }
             }
         }
@@ -453,36 +456,37 @@ Seqer_generate_i(Seqer *self) {
 
 static void
 Seqer_generate_a(Seqer *self) {
-    double tm;
     int i;
 
     MYFLT *time = Stream_getData((Stream *)self->time_stream);
 
-    if (self->currentTime == -1.0) {
-        self->currentTime = time[0];
-    }
-
     for (i=0; i<(self->poly*self->bufsize); i++) {
         self->buffer_streams[i] = 0.0;
     }
 
+    if (self->to_stop) {
+        PyObject_CallMethod((PyObject *)self, "stop", NULL);
+        self->to_stop = 0;
+        return;
+    }
+
     for (i=0; i<self->bufsize; i++) {
-        tm = (double)time[i];
         self->currentTime += self->sampleToSec;
-        if (self->currentTime >= tm) {
-            self->currentTime -= tm;
-            self->count++;
-            if (self->count >= self->seq[self->tap]) {
-                self->count = 0;
-                self->buffer_streams[i + self->voiceCount * self->bufsize] = 1.0;
-                self->voiceCount++;
-                if (self->voiceCount >= self->poly)
-                    self->voiceCount = 0;
-                self->tap++;
-                if (self->tap >= self->seqsize) {
-                    self->tap = 0;
-                    if (self->newseq == 1)
-                        Seqer_reset(self);
+        if (self->currentTime >= self->when) {
+            self->currentTime -= self->when;
+            self->when = self->seq[self->tap] * (double)time[i];
+            self->buffer_streams[i + self->voiceCount * self->bufsize] = 1.0;
+            self->voiceCount++;
+            if (self->voiceCount >= self->poly)
+                self->voiceCount = 0;
+            self->tap++;
+            if (self->tap >= self->seqsize) {
+                self->tap = 0;
+                if (self->newseq == 1)
+                    Seqer_reset(self);
+                if (self->onlyonce) {
+                    self->to_stop = 1;
+                    return;
                 }
             }
         }
@@ -539,6 +543,7 @@ static void
 Seqer_dealloc(Seqer* self)
 {
     pyo_DEALLOC
+    free(self->seq);
     free(self->buffer_streams);
     Seqer_clear(self);
     Py_TYPE(self)->tp_free((PyObject*)self);
@@ -553,16 +558,15 @@ Seqer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self = (Seqer *)type->tp_alloc(type, 0);
 
     self->time = PyFloat_FromDouble(1.);
-    self->flag = 1;
     self->poly = 1;
     self->seqsize = 1;
-    self->seq = (int *)realloc(self->seq, self->seqsize * sizeof(int));
-    self->seq[0] = 1;
+    self->seq = (double *)realloc(self->seq, self->seqsize * sizeof(double));
+    self->seq[0] = 1.0;
     self->newseq = 0;
-    self->duration = -1.0;
     self->tap = 0;
-    self->count = 0;
     self->voiceCount = 0;
+    self->onlyonce = 0;
+    self->to_stop = 0;
 	self->modebuffer[0] = 0;
 
     INIT_OBJECT_COMMON
@@ -572,11 +576,11 @@ Seqer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     Stream_setStreamActive(self->stream, 0);
 
     self->sampleToSec = 1.0 / self->sr;
-    self->currentTime = -1.0;
+    self->currentTime = 0.0;
 
-    static char *kwlist[] = {"time", "seq", "poly", NULL};
+    static char *kwlist[] = {"time", "seq", "poly", "onlyonce", NULL};
 
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOi", kwlist, &timetmp, &seqtmp, &self->poly))
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOii", kwlist, &timetmp, &seqtmp, &self->poly, &self->onlyonce))
         Py_RETURN_NONE;
 
     if (timetmp) {
@@ -586,6 +590,7 @@ Seqer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (seqtmp) {
         PyObject_CallMethod((PyObject *)self, "setSeq", "O", seqtmp);
     }
+    Seqer_reset(self);
 
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
@@ -599,7 +604,13 @@ Seqer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 static PyObject * Seqer_getServer(Seqer* self) { GET_SERVER };
 static PyObject * Seqer_getStream(Seqer* self) { GET_STREAM };
 
-static PyObject * Seqer_play(Seqer *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * Seqer_play(Seqer *self, PyObject *args, PyObject *kwds) { 
+    self->currentTime = 0.0;
+    self->when = 0.0;
+    self->tap = 0;
+    self->voiceCount = 0;
+    PLAY
+};
 static PyObject * Seqer_stop(Seqer *self) { STOP };
 
 static PyObject *
@@ -654,6 +665,21 @@ Seqer_setSeq(Seqer *self, PyObject *arg)
 	return Py_None;
 }
 
+static PyObject *
+Seqer_setOnlyonce(Seqer *self, PyObject *arg)
+{
+    ASSERT_ARG_NOT_NULL
+
+	int isInt = PyInt_Check(arg);
+
+	if (isInt == 1) {
+        self->onlyonce = PyLong_AsLong(arg);
+    }
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
 static PyMemberDef Seqer_members[] = {
     {"server", T_OBJECT_EX, offsetof(Seqer, server), 0, "Pyo server."},
     {"stream", T_OBJECT_EX, offsetof(Seqer, stream), 0, "Stream object."},
@@ -668,6 +694,7 @@ static PyMethodDef Seqer_methods[] = {
     {"stop", (PyCFunction)Seqer_stop, METH_NOARGS, "Stops computing."},
     {"setTime", (PyCFunction)Seqer_setTime, METH_O, "Sets time factor."},
     {"setSeq", (PyCFunction)Seqer_setSeq, METH_O, "Sets duration sequence."},
+    {"setOnlyonce", (PyCFunction)Seqer_setOnlyonce, METH_O, "Sets onlyonce attribute."},
     {NULL}  /* Sentinel */
 };
 
@@ -1745,6 +1772,8 @@ typedef struct {
     MYFLT tapDur;
     double sampleToSec;
     double currentTime;
+    int onlyonce;
+    int to_stop;
     MYFLT *buffer_streams;
     MYFLT *tap_buffer_streams;
     MYFLT *amp_buffer_streams;
@@ -1964,6 +1993,12 @@ Beater_generate_i(Beater *self) {
         self->buffer_streams[i] = self->end_buffer_streams[i] = 0.0;
     }
 
+    if (self->to_stop) {
+        PyObject_CallMethod((PyObject *)self, "stop", NULL);
+        self->to_stop = 0;
+        return;
+    }
+
     for (i=0; i<self->bufsize; i++) {
         self->tap_buffer_streams[i + self->voiceCount * self->bufsize] = (MYFLT)self->currentTap;
         for (j=0; j<self->poly; j++) {
@@ -1972,8 +2007,9 @@ Beater_generate_i(Beater *self) {
         self->dur_buffer_streams[i + self->voiceCount * self->bufsize] = self->durations[self->tapCount];
         if (self->currentTime >= tm) {
             self->currentTime -= tm;
-            if (self->tapCount == (self->last_taps-2))
+            if (self->tapCount == (self->last_taps-2)) {
                 self->end_buffer_streams[i + self->voiceCount * self->bufsize] = 1.0;
+            }
             if (self->sequence[self->tapCount] == 1) {
                 self->currentTap = self->tapCount;
                 self->amplitudes[self->voiceCount] = self->accentTable[self->tapCount];
@@ -2009,6 +2045,10 @@ Beater_generate_i(Beater *self) {
                     Beater_makeTable(self, 0);
                     Beater_makeSequence(self);
                 }
+                if (self->onlyonce) {
+                    self->to_stop = 1;
+                    return;
+                }
             }
         }
         self->currentTime += self->sampleToSec;
@@ -2033,6 +2073,12 @@ Beater_generate_a(Beater *self) {
         self->buffer_streams[i] = self->end_buffer_streams[i] = 0.0;
     }
 
+    if (self->to_stop) {
+        PyObject_CallMethod((PyObject *)self, "stop", NULL);
+        self->to_stop = 0;
+        return;
+    }
+
     for (i=0; i<self->bufsize; i++) {
         tm = (double)time[i];
         self->tap_buffer_streams[i + self->voiceCount * self->bufsize] = (MYFLT)self->currentTap;
@@ -2080,6 +2126,10 @@ Beater_generate_a(Beater *self) {
                     Beater_makeTable(self, 0);
                     Beater_makeSequence(self);
                 }
+                if (self->onlyonce) {
+                    self->to_stop = 1;
+                    return;
+                }
             }
         }
         self->currentTime += self->sampleToSec;
@@ -2186,6 +2236,8 @@ Beater_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->time = PyFloat_FromDouble(0.125);
     self->tapDur = 0.125;
     self->poly = 1;
+    self->onlyonce = 0;
+    self->to_stop = 0;
     self->voiceCount = 0;
 	self->modebuffer[0] = 0;
 
@@ -2208,9 +2260,9 @@ Beater_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
     Stream_setStreamActive(self->stream, 0);
 
-    static char *kwlist[] = {"time", "taps", "weight1", "weight2", "weight3", "poly", NULL};
+    static char *kwlist[] = {"time", "taps", "weight1", "weight2", "weight3", "poly", "onlyonce", NULL};
 
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "|Oiiiii", kwlist, &timetmp, &self->taps, &self->weight1, &self->weight2, &self->weight3, &self->poly))
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "|Oiiiiii", kwlist, &timetmp, &self->taps, &self->weight1, &self->weight2, &self->weight3, &self->poly, &self->onlyonce))
         Py_RETURN_NONE;
 
     if (timetmp) {
@@ -2245,7 +2297,14 @@ Beater_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 static PyObject * Beater_getServer(Beater* self) { GET_SERVER };
 static PyObject * Beater_getStream(Beater* self) { GET_STREAM };
 
-static PyObject * Beater_play(Beater *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * Beater_play(Beater *self, PyObject *args, PyObject *kwds) {
+    self->to_stop = 0;
+    self->voiceCount = 0;
+    self->tapCount = 0;
+    self->currentTap = 0;
+    self->currentTime = -1.0;
+    PLAY
+};
 static PyObject * Beater_stop(Beater *self) { STOP };
 
 static PyObject *
@@ -2329,9 +2388,17 @@ Beater_setWeights(Beater *self, PyObject *args, PyObject *kwds)
 }
 
 static PyObject *
-Beater_newPattern(Beater *self)
+Beater_newPattern(Beater *self, PyObject *arg)
 {
-    self->newFlag = 1;
+    if (PyInt_Check(arg)) {
+        if (PyInt_AsLong(arg)) {
+            Beater_makeTable(self, 0);
+            Beater_makeSequence(self);
+        }
+        else {
+            self->newFlag = 1;
+        }
+    }
 	Py_INCREF(Py_None);
 	return Py_None;
 }
@@ -2421,6 +2488,21 @@ Beater_setPresets(Beater *self, PyObject *arg) {
     return Py_None;
 }
 
+static PyObject *
+Beater_setOnlyonce(Beater *self, PyObject *arg)
+{
+    ASSERT_ARG_NOT_NULL
+
+	int isInt = PyInt_Check(arg);
+
+	if (isInt == 1) {
+        self->onlyonce = PyLong_AsLong(arg);
+    }
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
 static PyMemberDef Beater_members[] = {
     {"server", T_OBJECT_EX, offsetof(Beater, server), 0, "Pyo server."},
     {"stream", T_OBJECT_EX, offsetof(Beater, stream), 0, "Stream object."},
@@ -2436,12 +2518,13 @@ static PyMethodDef Beater_methods[] = {
     {"setTime", (PyCFunction)Beater_setTime, METH_O, "Sets tap duration."},
     {"setTaps", (PyCFunction)Beater_setTaps, METH_O, "Sets number of taps in the pattern."},
     {"setWeights", (PyCFunction)Beater_setWeights, METH_VARARGS|METH_KEYWORDS, "Sets probabilities for time accents in the pattern."},
-    {"new", (PyCFunction)Beater_newPattern, METH_NOARGS, "Generates a new pattern."},
+    {"new", (PyCFunction)Beater_newPattern, METH_O, "Generates a new pattern."},
     {"fill", (PyCFunction)Beater_fillPattern, METH_NOARGS, "Generates a fillin pattern and then restore the current pattern."},
     {"store", (PyCFunction)Beater_storePreset, METH_O, "Store the current pattern in a memory slot."},
     {"recall", (PyCFunction)Beater_recallPreset, METH_O, "Recall a pattern previously stored in a memory slot."},
     {"getPresets", (PyCFunction)Beater_getPresets, METH_NOARGS, "Returns the list of stored presets."},
     {"setPresets", (PyCFunction)Beater_setPresets, METH_O, "Store a list of presets."},
+    {"setOnlyonce", (PyCFunction)Beater_setOnlyonce, METH_O, "Sets onlyonce attribute."},
     {"reset", (PyCFunction)Beater_reset, METH_NOARGS, "Resets counters to 0."},
     {NULL}  /* Sentinel */
 };
diff --git a/src/objects/midimodule.c b/src/objects/midimodule.c
index a07b7c6..f5d4f98 100644
--- a/src/objects/midimodule.c
+++ b/src/objects/midimodule.c
@@ -48,8 +48,8 @@ CtlScan_compute_next_data_frame(CtlScan *self)
 
     if (count > 0) {
         PyObject *tup;
-        for (i=count-1; i>=0; i--) {
-            int status = PyoMidi_MessageStatus(buffer[i].message);	// Temp note event holders
+        for (i=0; i<count; i++) {
+            int status = PyoMidi_MessageStatus(buffer[i].message);    // Temp note event holders
             int number = PyoMidi_MessageData1(buffer[i].message);
             int value = PyoMidi_MessageData2(buffer[i].message);
 
@@ -130,40 +130,40 @@ static PyObject *
 CtlScan_reset(CtlScan *self)
 {
     self->ctlnumber = -1;
-	Py_INCREF(Py_None);
-	return Py_None;
+    Py_INCREF(Py_None);
+    return Py_None;
 };
 
 static PyObject *
 CtlScan_setFunction(CtlScan *self, PyObject *arg)
 {
-	PyObject *tmp;
+    PyObject *tmp;
 
-	if (! PyCallable_Check(arg)) {
+    if (! PyCallable_Check(arg)) {
         PyErr_SetString(PyExc_TypeError, "The callable attribute must be a valid Python function.");
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
+        Py_INCREF(Py_None);
+        return Py_None;
+    }
 
     tmp = arg;
     Py_XDECREF(self->callable);
     Py_INCREF(tmp);
     self->callable = tmp;
 
-	Py_INCREF(Py_None);
-	return Py_None;
+    Py_INCREF(Py_None);
+    return Py_None;
 }
 
 static PyObject *
 CtlScan_setToprint(CtlScan *self, PyObject *arg)
 {
 
-	if (PyInt_Check(arg)) {
-	    self->toprint = PyInt_AsLong(arg);
+    if (PyInt_Check(arg)) {
+        self->toprint = PyInt_AsLong(arg);
     }
 
-	Py_INCREF(Py_None);
-	return Py_None;
+    Py_INCREF(Py_None);
+    return Py_None;
 }
 static PyMemberDef CtlScan_members[] = {
     {"server", T_OBJECT_EX, offsetof(CtlScan, server), 0, "Pyo server."},
@@ -206,10 +206,10 @@ PyTypeObject CtlScanType = {
     "CtlScan objects. Retreive controller numbers from a Midi input.",           /* tp_doc */
     (traverseproc)CtlScan_traverse,   /* tp_traverse */
     (inquiry)CtlScan_clear,           /* tp_clear */
-    0,		               /* tp_richcompare */
-    0,		               /* tp_weaklistoffset */
-    0,		               /* tp_iter */
-    0,		               /* tp_iternext */
+    0,                     /* tp_richcompare */
+    0,                     /* tp_weaklistoffset */
+    0,                     /* tp_iter */
+    0,                     /* tp_iternext */
     CtlScan_methods,             /* tp_methods */
     CtlScan_members,             /* tp_members */
     0,                      /* tp_getset */
@@ -245,8 +245,8 @@ CtlScan2_compute_next_data_frame(CtlScan2 *self)
 
     if (count > 0) {
         PyObject *tup;
-        for (i=count-1; i>=0; i--) {
-            int status = PyoMidi_MessageStatus(buffer[i].message);	// Temp note event holders
+        for (i=0; i<count; i++) {
+            int status = PyoMidi_MessageStatus(buffer[i].message); // Temp note event holders
             int number = PyoMidi_MessageData1(buffer[i].message);
             int value = PyoMidi_MessageData2(buffer[i].message);
 
@@ -330,40 +330,40 @@ static PyObject *
 CtlScan2_reset(CtlScan2 *self)
 {
     self->ctlnumber = self->midichnl = -1;
-	Py_INCREF(Py_None);
-	return Py_None;
+    Py_INCREF(Py_None);
+    return Py_None;
 };
 
 static PyObject *
 CtlScan2_setFunction(CtlScan2 *self, PyObject *arg)
 {
-	PyObject *tmp;
+    PyObject *tmp;
 
-	if (! PyCallable_Check(arg)) {
+    if (! PyCallable_Check(arg)) {
         PyErr_SetString(PyExc_TypeError, "The callable attribute must be a valid Python function.");
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
+        Py_INCREF(Py_None);
+        return Py_None;
+    }
 
     tmp = arg;
     Py_XDECREF(self->callable);
     Py_INCREF(tmp);
     self->callable = tmp;
 
-	Py_INCREF(Py_None);
-	return Py_None;
+    Py_INCREF(Py_None);
+    return Py_None;
 }
 
 static PyObject *
 CtlScan2_setToprint(CtlScan2 *self, PyObject *arg)
 {
 
-	if (PyInt_Check(arg)) {
-	    self->toprint = PyInt_AsLong(arg);
+    if (PyInt_Check(arg)) {
+        self->toprint = PyInt_AsLong(arg);
     }
 
-	Py_INCREF(Py_None);
-	return Py_None;
+    Py_INCREF(Py_None);
+    return Py_None;
 }
 static PyMemberDef CtlScan2_members[] = {
     {"server", T_OBJECT_EX, offsetof(CtlScan2, server), 0, "Pyo server."},
@@ -406,10 +406,10 @@ PyTypeObject CtlScan2Type = {
     "CtlScan2 objects. Retreive midi channel and controller numbers from a midi input.",           /* tp_doc */
     (traverseproc)CtlScan2_traverse,   /* tp_traverse */
     (inquiry)CtlScan2_clear,           /* tp_clear */
-    0,		               /* tp_richcompare */
-    0,		               /* tp_weaklistoffset */
-    0,		               /* tp_iter */
-    0,		               /* tp_iternext */
+    0,                       /* tp_richcompare */
+    0,                       /* tp_weaklistoffset */
+    0,                       /* tp_iter */
+    0,                       /* tp_iternext */
     CtlScan2_methods,             /* tp_methods */
     CtlScan2_members,             /* tp_members */
     0,                      /* tp_getset */
@@ -453,7 +453,7 @@ Midictl_setProcMode(Midictl *self)
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
 
-	switch (muladdmode) {
+    switch (muladdmode) {
         case 0:
             self->muladd_func_ptr = Midictl_postprocessing_ii;
             break;
@@ -488,8 +488,8 @@ Midictl_setProcMode(Midictl *self)
 void translateMidi(Midictl *self, PyoMidiEvent *buffer, int count)
 {
     int i, ok;
-    for (i=count-1; i>=0; i--) {
-        int status = PyoMidi_MessageStatus(buffer[i].message);	// Temp note event holders
+    for (i=0; i<count; i++) {
+        int status = PyoMidi_MessageStatus(buffer[i].message);    // Temp note event holders
         int number = PyoMidi_MessageData1(buffer[i].message);
         int value = PyoMidi_MessageData2(buffer[i].message);
 
@@ -507,11 +507,11 @@ void translateMidi(Midictl *self, PyoMidiEvent *buffer, int count)
         }
 
         if (ok == 1 && number == self->ctlnumber) {
-            self->oldValue = self->value;
             self->value = (value / 127.) * (self->maxscale - self->minscale) + self->minscale;
             break;
         }
     }
+    self->oldValue = self->value;
 }
 
 static void
@@ -576,9 +576,9 @@ Midictl_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->oldValue = 0.;
     self->minscale = 0.;
     self->maxscale = 1.;
-    self->interp = 1;
-	self->modebuffer[0] = 0;
-	self->modebuffer[1] = 0;
+    self->interp = 0;
+    self->modebuffer[0] = 0;
+    self->modebuffer[1] = 0;
 
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Midictl_compute_next_data_frame);
@@ -632,18 +632,18 @@ Midictl_setInterpolation(Midictl *self, PyObject *arg)
 
     ASSERT_ARG_NOT_NULL
 
-	int isNum = PyInt_Check(arg);
+    int isNum = PyInt_Check(arg);
 
-	if (isNum == 1) {
-		tmp = PyInt_AsLong(arg);
+    if (isNum == 1) {
+        tmp = PyInt_AsLong(arg);
         if (tmp == 0)
             self->interp = 0;
         else
             self->interp = 1;
-	}
+    }
 
-	Py_INCREF(Py_None);
-	return Py_None;
+    Py_INCREF(Py_None);
+    return Py_None;
 }
 
 static PyObject *
@@ -653,15 +653,15 @@ Midictl_setValue(Midictl *self, PyObject *arg)
 
     ASSERT_ARG_NOT_NULL
 
-	int isNum = PyNumber_Check(arg);
+    int isNum = PyNumber_Check(arg);
 
-	if (isNum == 1) {
-		tmp = PyFloat_AsDouble(arg);
+    if (isNum == 1) {
+        tmp = PyFloat_AsDouble(arg);
         self->oldValue = self->value = tmp;
-	}
+    }
 
-	Py_INCREF(Py_None);
-	return Py_None;
+    Py_INCREF(Py_None);
+    return Py_None;
 }
 
 static PyObject *
@@ -671,15 +671,15 @@ Midictl_setMinScale(Midictl *self, PyObject *arg)
 
     ASSERT_ARG_NOT_NULL
 
-	int isNum = PyNumber_Check(arg);
+    int isNum = PyNumber_Check(arg);
 
-	if (isNum == 1) {
-		tmp = PyFloat_AsDouble(arg);
+    if (isNum == 1) {
+        tmp = PyFloat_AsDouble(arg);
         self->minscale = tmp;
-	}
+    }
 
-	Py_INCREF(Py_None);
-	return Py_None;
+    Py_INCREF(Py_None);
+    return Py_None;
 }
 
 static PyObject *
@@ -689,15 +689,15 @@ Midictl_setMaxScale(Midictl *self, PyObject *arg)
 
     ASSERT_ARG_NOT_NULL
 
-	int isNum = PyNumber_Check(arg);
+    int isNum = PyNumber_Check(arg);
 
-	if (isNum == 1) {
-		tmp = PyFloat_AsDouble(arg);
+    if (isNum == 1) {
+        tmp = PyFloat_AsDouble(arg);
         self->maxscale = tmp;
-	}
+    }
 
-	Py_INCREF(Py_None);
-	return Py_None;
+    Py_INCREF(Py_None);
+    return Py_None;
 }
 
 static PyObject *
@@ -707,16 +707,16 @@ Midictl_setCtlNumber(Midictl *self, PyObject *arg)
 
     ASSERT_ARG_NOT_NULL
 
-	int isInt = PyInt_Check(arg);
+    int isInt = PyInt_Check(arg);
 
-	if (isInt == 1) {
-		tmp = PyInt_AsLong(arg);
+    if (isInt == 1) {
+        tmp = PyInt_AsLong(arg);
         if (tmp >= 0 && tmp < 128)
             self->ctlnumber = tmp;
-	}
+    }
 
-	Py_INCREF(Py_None);
-	return Py_None;
+    Py_INCREF(Py_None);
+    return Py_None;
 }
 
 static PyObject *
@@ -726,16 +726,16 @@ Midictl_setChannel(Midictl *self, PyObject *arg)
 
     ASSERT_ARG_NOT_NULL
 
-	int isInt = PyInt_Check(arg);
+    int isInt = PyInt_Check(arg);
 
-	if (isInt == 1) {
-		tmp = PyInt_AsLong(arg);
+    if (isInt == 1) {
+        tmp = PyInt_AsLong(arg);
         if (tmp >= 0 && tmp < 128)
             self->channel = tmp;
-	}
+    }
 
-	Py_INCREF(Py_None);
-	return Py_None;
+    Py_INCREF(Py_None);
+    return Py_None;
 }
 
 static PyMemberDef Midictl_members[] = {
@@ -751,14 +751,14 @@ static PyMethodDef Midictl_methods[] = {
     {"_getStream", (PyCFunction)Midictl_getStream, METH_NOARGS, "Returns stream object."},
     {"play", (PyCFunction)Midictl_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
     {"stop", (PyCFunction)Midictl_stop, METH_NOARGS, "Stops computing."},
-	{"setInterpolation", (PyCFunction)Midictl_setInterpolation, METH_O, "Activate/Deactivate interpolation."},
-	{"setValue", (PyCFunction)Midictl_setValue, METH_O, "Resets audio stream to value in argument."},
-	{"setMinScale", (PyCFunction)Midictl_setMinScale, METH_O, "Sets the minimum value of scaling."},
-	{"setMaxScale", (PyCFunction)Midictl_setMaxScale, METH_O, "Sets the maximum value of scaling."},
-	{"setCtlNumber", (PyCFunction)Midictl_setCtlNumber, METH_O, "Sets the controller number."},
-	{"setChannel", (PyCFunction)Midictl_setChannel, METH_O, "Sets the midi channel."},
-	{"setMul", (PyCFunction)Midictl_setMul, METH_O, "Sets oscillator mul factor."},
-	{"setAdd", (PyCFunction)Midictl_setAdd, METH_O, "Sets oscillator add factor."},
+    {"setInterpolation", (PyCFunction)Midictl_setInterpolation, METH_O, "Activate/Deactivate interpolation."},
+    {"setValue", (PyCFunction)Midictl_setValue, METH_O, "Resets audio stream to value in argument."},
+    {"setMinScale", (PyCFunction)Midictl_setMinScale, METH_O, "Sets the minimum value of scaling."},
+    {"setMaxScale", (PyCFunction)Midictl_setMaxScale, METH_O, "Sets the maximum value of scaling."},
+    {"setCtlNumber", (PyCFunction)Midictl_setCtlNumber, METH_O, "Sets the controller number."},
+    {"setChannel", (PyCFunction)Midictl_setChannel, METH_O, "Sets the midi channel."},
+    {"setMul", (PyCFunction)Midictl_setMul, METH_O, "Sets oscillator mul factor."},
+    {"setAdd", (PyCFunction)Midictl_setAdd, METH_O, "Sets oscillator add factor."},
     {"setSub", (PyCFunction)Midictl_setSub, METH_O, "Sets inverse add factor."},
     {"setDiv", (PyCFunction)Midictl_setDiv, METH_O, "Sets inverse mul factor."},
     {NULL}  /* Sentinel */
@@ -830,10 +830,10 @@ PyTypeObject MidictlType = {
     "Midictl objects. Retreive audio from an input channel.",           /* tp_doc */
     (traverseproc)Midictl_traverse,   /* tp_traverse */
     (inquiry)Midictl_clear,           /* tp_clear */
-    0,		               /* tp_richcompare */
-    0,		               /* tp_weaklistoffset */
-    0,		               /* tp_iter */
-    0,		               /* tp_iternext */
+    0,                       /* tp_richcompare */
+    0,                       /* tp_weaklistoffset */
+    0,                       /* tp_iter */
+    0,                       /* tp_iternext */
     Midictl_methods,             /* tp_methods */
     Midictl_members,             /* tp_members */
     0,                      /* tp_getset */
@@ -851,6 +851,7 @@ typedef struct {
     pyo_audio_HEAD
     int channel;
     int scale; /* 0 = midi, 1 = transpo */
+    int interp;
     MYFLT range;
     MYFLT value;
     MYFLT oldValue;
@@ -874,7 +875,7 @@ Bendin_setProcMode(Bendin *self)
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
 
-	switch (muladdmode) {
+    switch (muladdmode) {
         case 0:
             self->muladd_func_ptr = Bendin_postprocessing_ii;
             break;
@@ -910,8 +911,8 @@ void Bendin_translateMidi(Bendin *self, PyoMidiEvent *buffer, int count)
 {
     int i, ok;
     MYFLT val;
-    for (i=count-1; i>=0; i--) {
-        int status = PyoMidi_MessageStatus(buffer[i].message);	// Temp note event holders
+    for (i=0; i<count; i++) {
+        int status = PyoMidi_MessageStatus(buffer[i].message);    // Temp note event holders
         int number = PyoMidi_MessageData1(buffer[i].message);
         int value = PyoMidi_MessageData2(buffer[i].message);
 
@@ -929,7 +930,6 @@ void Bendin_translateMidi(Bendin *self, PyoMidiEvent *buffer, int count)
         }
 
         if (ok == 1) {
-            self->oldValue = self->value;
             val = (number + (value << 7) - 8192) / 8192.0 * self->range;
             if (self->scale == 0)
                 self->value = val;
@@ -938,6 +938,7 @@ void Bendin_translateMidi(Bendin *self, PyoMidiEvent *buffer, int count)
             break;
         }
     }
+    self->oldValue = self->value;
 }
 
 static void
@@ -948,13 +949,19 @@ Bendin_compute_next_data_frame(Bendin *self)
 
     tmp = Server_getMidiEventBuffer((Server *)self->server);
     count = Server_getMidiEventCount((Server *)self->server);
-
     if (count > 0)
         Bendin_translateMidi((Bendin *)self, tmp, count);
-    MYFLT step = (self->value - self->oldValue) / self->bufsize;
 
-    for (i=0; i<self->bufsize; i++) {
-        self->data[i] = self->oldValue + step;
+    if (self->interp == 0) {
+        for (i=0; i<self->bufsize; i++) {
+            self->data[i] = self->value;
+        }
+    }
+    else {
+        MYFLT step = (self->value - self->oldValue) / self->bufsize;
+        for (i=0; i<self->bufsize; i++) {
+            self->data[i] = self->oldValue + step;
+        }
     }
 
     (*self->muladd_func_ptr)(self);
@@ -992,11 +999,12 @@ Bendin_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
     self->channel = 0;
     self->scale = 0;
+    self->interp = 0;
     self->value = 0.;
     self->oldValue = 0.;
     self->range = 2.;
-	self->modebuffer[0] = 0;
-	self->modebuffer[1] = 0;
+    self->modebuffer[0] = 0;
+    self->modebuffer[1] = 0;
 
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Bendin_compute_next_data_frame);
@@ -1053,16 +1061,16 @@ Bendin_setBrange(Bendin *self, PyObject *arg)
 
     ASSERT_ARG_NOT_NULL
 
-	int isNum = PyNumber_Check(arg);
+    int isNum = PyNumber_Check(arg);
 
-	if (isNum == 1) {
-		tmp = PyFloat_AsDouble(arg);
+    if (isNum == 1) {
+        tmp = PyFloat_AsDouble(arg);
         if (tmp >= 0.0 && tmp < 128.0)
             self->range = tmp;
-	}
+    }
 
-	Py_INCREF(Py_None);
-	return Py_None;
+    Py_INCREF(Py_None);
+    return Py_None;
 }
 
 static PyObject *
@@ -1072,16 +1080,16 @@ Bendin_setChannel(Bendin *self, PyObject *arg)
 
     ASSERT_ARG_NOT_NULL
 
-	int isInt = PyInt_Check(arg);
+    int isInt = PyInt_Check(arg);
 
-	if (isInt == 1) {
-		tmp = PyInt_AsLong(arg);
+    if (isInt == 1) {
+        tmp = PyInt_AsLong(arg);
         if (tmp >= 0 && tmp < 128)
             self->channel = tmp;
-	}
+    }
 
-	Py_INCREF(Py_None);
-	return Py_None;
+    Py_INCREF(Py_None);
+    return Py_None;
 }
 
 static PyObject *
@@ -1105,6 +1113,26 @@ Bendin_setScale(Bendin *self, PyObject *arg)
     return Py_None;
 }
 
+static PyObject *
+Bendin_setInterpolation(Bendin *self, PyObject *arg)
+{
+    int tmp;
+
+    ASSERT_ARG_NOT_NULL
+
+    int isNum = PyInt_Check(arg);
+
+    if (isNum == 1) {
+        tmp = PyInt_AsLong(arg);
+        if (tmp == 0)
+            self->interp = 0;
+        else
+            self->interp = 1;
+    }
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
 
 static PyMemberDef Bendin_members[] = {
     {"server", T_OBJECT_EX, offsetof(Bendin, server), 0, "Pyo server."},
@@ -1119,11 +1147,12 @@ static PyMethodDef Bendin_methods[] = {
     {"_getStream", (PyCFunction)Bendin_getStream, METH_NOARGS, "Returns stream object."},
     {"play", (PyCFunction)Bendin_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
     {"stop", (PyCFunction)Bendin_stop, METH_NOARGS, "Stops computing."},
-	{"setBrange", (PyCFunction)Bendin_setBrange, METH_O, "Sets the bending bipolar range."},
-	{"setScale", (PyCFunction)Bendin_setScale, METH_O, "Sets the output type, midi vs transpo."},
-	{"setChannel", (PyCFunction)Bendin_setChannel, METH_O, "Sets the midi channel."},
-	{"setMul", (PyCFunction)Bendin_setMul, METH_O, "Sets oscillator mul factor."},
-	{"setAdd", (PyCFunction)Bendin_setAdd, METH_O, "Sets oscillator add factor."},
+    {"setBrange", (PyCFunction)Bendin_setBrange, METH_O, "Sets the bending bipolar range."},
+    {"setScale", (PyCFunction)Bendin_setScale, METH_O, "Sets the output type, midi vs transpo."},
+    {"setChannel", (PyCFunction)Bendin_setChannel, METH_O, "Sets the midi channel."},
+    {"setInterpolation", (PyCFunction)Bendin_setInterpolation, METH_O, "Activate/Deactivate interpolation."},
+    {"setMul", (PyCFunction)Bendin_setMul, METH_O, "Sets oscillator mul factor."},
+    {"setAdd", (PyCFunction)Bendin_setAdd, METH_O, "Sets oscillator add factor."},
     {"setSub", (PyCFunction)Bendin_setSub, METH_O, "Sets inverse add factor."},
     {"setDiv", (PyCFunction)Bendin_setDiv, METH_O, "Sets inverse mul factor."},
     {NULL}  /* Sentinel */
@@ -1195,10 +1224,10 @@ PyTypeObject BendinType = {
     "Bendin objects. Retreive audio from an input channel.",           /* tp_doc */
     (traverseproc)Bendin_traverse,   /* tp_traverse */
     (inquiry)Bendin_clear,           /* tp_clear */
-    0,		               /* tp_richcompare */
-    0,		               /* tp_weaklistoffset */
-    0,		               /* tp_iter */
-    0,		               /* tp_iternext */
+    0,                       /* tp_richcompare */
+    0,                       /* tp_weaklistoffset */
+    0,                       /* tp_iter */
+    0,                       /* tp_iternext */
     Bendin_methods,             /* tp_methods */
     Bendin_members,             /* tp_members */
     0,                      /* tp_getset */
@@ -1217,6 +1246,7 @@ typedef struct {
     int channel;
     MYFLT minscale;
     MYFLT maxscale;
+    int interp;
     MYFLT value;
     MYFLT oldValue;
     MYFLT sampleToSec;
@@ -1239,7 +1269,7 @@ Touchin_setProcMode(Touchin *self)
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
 
-	switch (muladdmode) {
+    switch (muladdmode) {
         case 0:
             self->muladd_func_ptr = Touchin_postprocessing_ii;
             break;
@@ -1274,10 +1304,9 @@ Touchin_setProcMode(Touchin *self)
 void Touchin_translateMidi(Touchin *self, PyoMidiEvent *buffer, int count)
 {
     int i, ok;
-    for (i=count-1; i>=0; i--) {
-        int status = PyoMidi_MessageStatus(buffer[i].message);	// Temp note event holders
+    for (i=0; i<count; i++) {
+        int status = PyoMidi_MessageStatus(buffer[i].message);    // Temp note event holders
         int number = PyoMidi_MessageData1(buffer[i].message);
-        /* int value = PyoMidi_MessageData2(buffer[i].message); */
 
         if (self->channel == 0) {
             if ((status & 0xF0) == 0xd0)
@@ -1293,11 +1322,11 @@ void Touchin_translateMidi(Touchin *self, PyoMidiEvent *buffer, int count)
         }
 
         if (ok == 1) {
-            self->oldValue = self->value;
             self->value = (number / 127.) * (self->maxscale - self->minscale) + self->minscale;
             break;
         }
     }
+    self->oldValue = self->value;
 }
 
 static void
@@ -1311,10 +1340,17 @@ Touchin_compute_next_data_frame(Touchin *self)
 
     if (count > 0)
         Touchin_translateMidi((Touchin *)self, tmp, count);
-    MYFLT step = (self->value - self->oldValue) / self->bufsize;
 
-    for (i=0; i<self->bufsize; i++) {
-        self->data[i] = self->oldValue + step;
+    if (self->interp == 0) {
+        for (i=0; i<self->bufsize; i++) {
+            self->data[i] = self->value;
+        }
+    }
+    else {
+        MYFLT step = (self->value - self->oldValue) / self->bufsize;
+        for (i=0; i<self->bufsize; i++) {
+            self->data[i] = self->oldValue + step;
+        }
     }
 
     (*self->muladd_func_ptr)(self);
@@ -1355,8 +1391,9 @@ Touchin_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->oldValue = 0.;
     self->minscale = 0.;
     self->maxscale = 1.;
-	self->modebuffer[0] = 0;
-	self->modebuffer[1] = 0;
+    self->interp = 0;
+    self->modebuffer[0] = 0;
+    self->modebuffer[1] = 0;
 
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Touchin_compute_next_data_frame);
@@ -1410,15 +1447,15 @@ Touchin_setMinScale(Touchin *self, PyObject *arg)
 
     ASSERT_ARG_NOT_NULL
 
-	int isNum = PyNumber_Check(arg);
+    int isNum = PyNumber_Check(arg);
 
-	if (isNum == 1) {
-		tmp = PyFloat_AsDouble(arg);
+    if (isNum == 1) {
+        tmp = PyFloat_AsDouble(arg);
             self->minscale = tmp;
-	}
+    }
 
-	Py_INCREF(Py_None);
-	return Py_None;
+    Py_INCREF(Py_None);
+    return Py_None;
 }
 
 static PyObject *
@@ -1428,15 +1465,15 @@ Touchin_setMaxScale(Touchin *self, PyObject *arg)
 
     ASSERT_ARG_NOT_NULL
 
-	int isNum = PyNumber_Check(arg);
+    int isNum = PyNumber_Check(arg);
 
-	if (isNum == 1) {
-		tmp = PyFloat_AsDouble(arg);
+    if (isNum == 1) {
+        tmp = PyFloat_AsDouble(arg);
         self->maxscale = tmp;
-	}
+    }
 
-	Py_INCREF(Py_None);
-	return Py_None;
+    Py_INCREF(Py_None);
+    return Py_None;
 }
 
 static PyObject *
@@ -1446,12 +1483,33 @@ Touchin_setChannel(Touchin *self, PyObject *arg)
 
     ASSERT_ARG_NOT_NULL
 
-	int isInt = PyInt_Check(arg);
+    int isInt = PyInt_Check(arg);
 
-	if (isInt == 1) {
-		tmp = PyInt_AsLong(arg);
+    if (isInt == 1) {
+        tmp = PyInt_AsLong(arg);
         if (tmp >= 0 && tmp < 128)
             self->channel = tmp;
+    }
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *
+Touchin_setInterpolation(Touchin *self, PyObject *arg)
+{
+    int tmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNum = PyInt_Check(arg);
+
+	if (isNum == 1) {
+		tmp = PyInt_AsLong(arg);
+        if (tmp == 0)
+            self->interp = 0;
+        else
+            self->interp = 1;
 	}
 
 	Py_INCREF(Py_None);
@@ -1471,11 +1529,12 @@ static PyMethodDef Touchin_methods[] = {
     {"_getStream", (PyCFunction)Touchin_getStream, METH_NOARGS, "Returns stream object."},
     {"play", (PyCFunction)Touchin_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
     {"stop", (PyCFunction)Touchin_stop, METH_NOARGS, "Stops computing."},
-	{"setMinScale", (PyCFunction)Touchin_setMinScale, METH_O, "Sets the minimum value of scaling."},
-	{"setMaxScale", (PyCFunction)Touchin_setMaxScale, METH_O, "Sets the maximum value of scaling."},
-	{"setChannel", (PyCFunction)Touchin_setChannel, METH_O, "Sets the midi channel."},
-	{"setMul", (PyCFunction)Touchin_setMul, METH_O, "Sets oscillator mul factor."},
-	{"setAdd", (PyCFunction)Touchin_setAdd, METH_O, "Sets oscillator add factor."},
+    {"setMinScale", (PyCFunction)Touchin_setMinScale, METH_O, "Sets the minimum value of scaling."},
+    {"setMaxScale", (PyCFunction)Touchin_setMaxScale, METH_O, "Sets the maximum value of scaling."},
+    {"setChannel", (PyCFunction)Touchin_setChannel, METH_O, "Sets the midi channel."},
+	{"setInterpolation", (PyCFunction)Touchin_setInterpolation, METH_O, "Activate/Deactivate interpolation."},
+    {"setMul", (PyCFunction)Touchin_setMul, METH_O, "Sets oscillator mul factor."},
+    {"setAdd", (PyCFunction)Touchin_setAdd, METH_O, "Sets oscillator add factor."},
     {"setSub", (PyCFunction)Touchin_setSub, METH_O, "Sets inverse add factor."},
     {"setDiv", (PyCFunction)Touchin_setDiv, METH_O, "Sets inverse mul factor."},
     {NULL}  /* Sentinel */
@@ -1547,10 +1606,10 @@ PyTypeObject TouchinType = {
     "Touchin objects. Retrieve the signal of an aftertouch midi controller.",           /* tp_doc */
     (traverseproc)Touchin_traverse,   /* tp_traverse */
     (inquiry)Touchin_clear,           /* tp_clear */
-    0,		               /* tp_richcompare */
-    0,		               /* tp_weaklistoffset */
-    0,		               /* tp_iter */
-    0,		               /* tp_iternext */
+    0,                       /* tp_richcompare */
+    0,                       /* tp_weaklistoffset */
+    0,                       /* tp_iter */
+    0,                       /* tp_iternext */
     Touchin_methods,             /* tp_methods */
     Touchin_members,             /* tp_members */
     0,                      /* tp_getset */
@@ -1587,7 +1646,7 @@ Programin_setProcMode(Programin *self)
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
 
-	switch (muladdmode) {
+    switch (muladdmode) {
         case 0:
             self->muladd_func_ptr = Programin_postprocessing_ii;
             break;
@@ -1623,8 +1682,8 @@ void Programin_translateMidi(Programin *self, PyoMidiEvent *buffer, int count)
 {
     int i, ok;
 
-    for (i=count-1; i>=0; i--) {
-        int status = PyoMidi_MessageStatus(buffer[i].message);	// Temp note event holders
+    for (i=0; i<count; i++) {
+        int status = PyoMidi_MessageStatus(buffer[i].message);    // Temp note event holders
         int number = PyoMidi_MessageData1(buffer[i].message);
 
         if (self->channel == 0) {
@@ -1698,8 +1757,8 @@ Programin_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
     self->channel = 0;
     self->value = 0.;
-	self->modebuffer[0] = 0;
-	self->modebuffer[1] = 0;
+    self->modebuffer[0] = 0;
+    self->modebuffer[1] = 0;
 
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Programin_compute_next_data_frame);
@@ -1751,16 +1810,16 @@ Programin_setChannel(Programin *self, PyObject *arg)
 
     ASSERT_ARG_NOT_NULL
 
-	int isInt = PyInt_Check(arg);
+    int isInt = PyInt_Check(arg);
 
-	if (isInt == 1) {
-		tmp = PyInt_AsLong(arg);
+    if (isInt == 1) {
+        tmp = PyInt_AsLong(arg);
         if (tmp >= 0 && tmp < 128)
             self->channel = tmp;
-	}
+    }
 
-	Py_INCREF(Py_None);
-	return Py_None;
+    Py_INCREF(Py_None);
+    return Py_None;
 }
 
 static PyMemberDef Programin_members[] = {
@@ -1776,9 +1835,9 @@ static PyMethodDef Programin_methods[] = {
     {"_getStream", (PyCFunction)Programin_getStream, METH_NOARGS, "Returns stream object."},
     {"play", (PyCFunction)Programin_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
     {"stop", (PyCFunction)Programin_stop, METH_NOARGS, "Stops computing."},
-	{"setChannel", (PyCFunction)Programin_setChannel, METH_O, "Sets the midi channel."},
-	{"setMul", (PyCFunction)Programin_setMul, METH_O, "Sets oscillator mul factor."},
-	{"setAdd", (PyCFunction)Programin_setAdd, METH_O, "Sets oscillator add factor."},
+    {"setChannel", (PyCFunction)Programin_setChannel, METH_O, "Sets the midi channel."},
+    {"setMul", (PyCFunction)Programin_setMul, METH_O, "Sets oscillator mul factor."},
+    {"setAdd", (PyCFunction)Programin_setAdd, METH_O, "Sets oscillator add factor."},
     {"setSub", (PyCFunction)Programin_setSub, METH_O, "Sets inverse add factor."},
     {"setDiv", (PyCFunction)Programin_setDiv, METH_O, "Sets inverse mul factor."},
     {NULL}  /* Sentinel */
@@ -1850,10 +1909,10 @@ PyTypeObject PrograminType = {
     "Programin objects. Retrieve the signal of a program change midi controller.",           /* tp_doc */
     (traverseproc)Programin_traverse,   /* tp_traverse */
     (inquiry)Programin_clear,           /* tp_clear */
-    0,		               /* tp_richcompare */
-    0,		               /* tp_weaklistoffset */
-    0,		               /* tp_iter */
-    0,		               /* tp_iternext */
+    0,                       /* tp_richcompare */
+    0,                       /* tp_weaklistoffset */
+    0,                       /* tp_iter */
+    0,                       /* tp_iternext */
     Programin_methods,             /* tp_methods */
     Programin_members,             /* tp_members */
     0,                      /* tp_getset */
@@ -1941,7 +2000,7 @@ void grabMidiNotes(MidiNote *self, PyoMidiEvent *buffer, int count)
     int i, ok, voice, kind;
 
     for (i=0; i<count; i++) {
-        int status = PyoMidi_MessageStatus(buffer[i].message);	// Temp note event holders
+        int status = PyoMidi_MessageStatus(buffer[i].message);    // Temp note event holders
         int pitch = PyoMidi_MessageData1(buffer[i].message);
         int velocity = PyoMidi_MessageData2(buffer[i].message);
 
@@ -2117,12 +2176,12 @@ MidiNote_setScale(MidiNote *self, PyObject *arg)
 {
     ASSERT_ARG_NOT_NULL
 
-	if (PyInt_Check(arg) == 1) {
-		int tmp = PyInt_AsLong(arg);
+    if (PyInt_Check(arg) == 1) {
+        int tmp = PyInt_AsLong(arg);
         if (tmp >= 0 && tmp < 3)
             self->scale = tmp;
-	}
-	Py_RETURN_NONE;
+    }
+    Py_RETURN_NONE;
 }
 
 static PyObject *
@@ -2130,12 +2189,12 @@ MidiNote_setFirst(MidiNote *self, PyObject *arg)
 {
     ASSERT_ARG_NOT_NULL
 
-	if (PyInt_Check(arg) == 1) {
-		int tmp = PyInt_AsLong(arg);
+    if (PyInt_Check(arg) == 1) {
+        int tmp = PyInt_AsLong(arg);
         if (tmp >= 0 && tmp < 128)
             self->first = tmp;
-	}
-	Py_RETURN_NONE;
+    }
+    Py_RETURN_NONE;
 }
 
 static PyObject *
@@ -2143,12 +2202,12 @@ MidiNote_setLast(MidiNote *self, PyObject *arg)
 {
     ASSERT_ARG_NOT_NULL
 
-	if (PyInt_Check(arg) == 1) {
-		int tmp = PyInt_AsLong(arg);
+    if (PyInt_Check(arg) == 1) {
+        int tmp = PyInt_AsLong(arg);
         if (tmp >= 0 && tmp < 128)
             self->last = tmp;
-	}
-	Py_RETURN_NONE;
+    }
+    Py_RETURN_NONE;
 }
 
 static PyObject *
@@ -2156,12 +2215,12 @@ MidiNote_setChannel(MidiNote *self, PyObject *arg)
 {
     ASSERT_ARG_NOT_NULL
 
-	if (PyInt_Check(arg) == 1) {
-		int tmp = PyInt_AsLong(arg);
+    if (PyInt_Check(arg) == 1) {
+        int tmp = PyInt_AsLong(arg);
         if (tmp >= 0 && tmp < 128)
             self->channel = tmp;
-	}
-	Py_RETURN_NONE;
+    }
+    Py_RETURN_NONE;
 }
 
 static PyObject *
@@ -2171,16 +2230,16 @@ MidiNote_setCentralKey(MidiNote *self, PyObject *arg)
 
     ASSERT_ARG_NOT_NULL
 
-	int isInt = PyInt_Check(arg);
+    int isInt = PyInt_Check(arg);
 
-	if (isInt == 1) {
-		tmp = PyInt_AsLong(arg);
+    if (isInt == 1) {
+        tmp = PyInt_AsLong(arg);
         if (tmp >= self->first && tmp <= self->last)
             self->centralkey = tmp;
-	}
+    }
 
-	Py_INCREF(Py_None);
-	return Py_None;
+    Py_INCREF(Py_None);
+    return Py_None;
 }
 
 static PyObject *
@@ -2188,13 +2247,13 @@ MidiNote_setStealing(MidiNote *self, PyObject *arg)
 {
     ASSERT_ARG_NOT_NULL
 
-	int isInt = PyInt_Check(arg);
+    int isInt = PyInt_Check(arg);
 
-	if (isInt == 1)
-		self->stealing = PyInt_AsLong(arg);
+    if (isInt == 1)
+        self->stealing = PyInt_AsLong(arg);
 
-	Py_INCREF(Py_None);
-	return Py_None;
+    Py_INCREF(Py_None);
+    return Py_None;
 }
 
 static PyMemberDef MidiNote_members[] = {
@@ -2241,10 +2300,10 @@ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECK
 "MidiNote objects. Retreive midi note from a midi input.",           /* tp_doc */
 (traverseproc)MidiNote_traverse,   /* tp_traverse */
 (inquiry)MidiNote_clear,           /* tp_clear */
-0,		               /* tp_richcompare */
-0,		               /* tp_weaklistoffset */
-0,		               /* tp_iter */
-0,		               /* tp_iternext */
+0,                       /* tp_richcompare */
+0,                       /* tp_weaklistoffset */
+0,                       /* tp_iter */
+0,                       /* tp_iternext */
 MidiNote_methods,             /* tp_methods */
 MidiNote_members,             /* tp_members */
 0,                      /* tp_getset */
@@ -2284,7 +2343,7 @@ Notein_setProcMode(Notein *self)
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
 
-	switch (muladdmode) {
+    switch (muladdmode) {
         case 0:
             self->muladd_func_ptr = Notein_postprocessing_ii;
             break;
@@ -2504,10 +2563,10 @@ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECK
 "Notein objects. Stream pitch or velocity from a Notein voice.",           /* tp_doc */
 (traverseproc)Notein_traverse,   /* tp_traverse */
 (inquiry)Notein_clear,           /* tp_clear */
-0,		               /* tp_richcompare */
-0,		               /* tp_weaklistoffset */
-0,		               /* tp_iter */
-0,		               /* tp_iternext */
+0,                       /* tp_richcompare */
+0,                       /* tp_weaklistoffset */
+0,                       /* tp_iter */
+0,                       /* tp_iternext */
 Notein_methods,             /* tp_methods */
 Notein_members,             /* tp_members */
 0,                      /* tp_getset */
@@ -2546,7 +2605,7 @@ NoteinTrig_setProcMode(NoteinTrig *self)
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
 
-	switch (muladdmode) {
+    switch (muladdmode) {
         case 0:
             self->muladd_func_ptr = NoteinTrig_postprocessing_ii;
             break;
@@ -2759,10 +2818,10 @@ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECK
 "NoteinTrig objects. Stream noteon or noteoff trigger from a Notein voice.",           /* tp_doc */
 (traverseproc)NoteinTrig_traverse,   /* tp_traverse */
 (inquiry)NoteinTrig_clear,           /* tp_clear */
-0,		               /* tp_richcompare */
-0,		               /* tp_weaklistoffset */
-0,		               /* tp_iter */
-0,		               /* tp_iternext */
+0,                       /* tp_richcompare */
+0,                       /* tp_weaklistoffset */
+0,                       /* tp_iter */
+0,                       /* tp_iternext */
 NoteinTrig_methods,             /* tp_methods */
 NoteinTrig_members,             /* tp_members */
 0,                      /* tp_getset */
@@ -2879,7 +2938,7 @@ MidiAdsr_setProcMode(MidiAdsr *self)
 
     self->proc_func_ptr = MidiAdsr_generates;
 
-	switch (muladdmode) {
+    switch (muladdmode) {
         case 0:
             self->muladd_func_ptr = MidiAdsr_postprocessing_ii;
             break;
@@ -2952,8 +3011,8 @@ MidiAdsr_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     MidiAdsr *self;
     self = (MidiAdsr *)type->tp_alloc(type, 0);
 
-	self->modebuffer[0] = 0;
-	self->modebuffer[1] = 0;
+    self->modebuffer[0] = 0;
+    self->modebuffer[1] = 0;
     self->topValue = 0.0;
     self->fademode = 0;
     self->changed = 0;
@@ -3030,7 +3089,7 @@ static PyObject * MidiAdsr_inplace_div(MidiAdsr *self, PyObject *arg) { INPLACE_
 static PyObject *
 MidiAdsr_setAttack(MidiAdsr *self, PyObject *arg)
 {
-	if (PyNumber_Check(arg)) {
+    if (PyNumber_Check(arg)) {
         self->attack = PyFloat_AsDouble(arg);
         if (self->attack < 0.000001)
             self->attack = 0.000001;
@@ -3044,7 +3103,7 @@ MidiAdsr_setAttack(MidiAdsr *self, PyObject *arg)
 static PyObject *
 MidiAdsr_setDecay(MidiAdsr *self, PyObject *arg)
 {
-	if (PyNumber_Check(arg)) {
+    if (PyNumber_Check(arg)) {
         self->decay = PyFloat_AsDouble(arg);
         if (self->decay < 0.000001)
             self->decay = 0.000001;
@@ -3058,7 +3117,7 @@ MidiAdsr_setDecay(MidiAdsr *self, PyObject *arg)
 static PyObject *
 MidiAdsr_setSustain(MidiAdsr *self, PyObject *arg)
 {
-	if (PyNumber_Check(arg)) {
+    if (PyNumber_Check(arg)) {
         self->sustain = PyFloat_AsDouble(arg);
         if (self->sustain < 0.0)
             self->sustain = 0.0;
@@ -3072,7 +3131,7 @@ MidiAdsr_setSustain(MidiAdsr *self, PyObject *arg)
 static PyObject *
 MidiAdsr_setRelease(MidiAdsr *self, PyObject *arg)
 {
-	if (PyNumber_Check(arg)) {
+    if (PyNumber_Check(arg)) {
         self->release = PyFloat_AsDouble(arg);
         if (self->release < 0.000001)
             self->release = 0.000001;
@@ -3085,7 +3144,7 @@ MidiAdsr_setRelease(MidiAdsr *self, PyObject *arg)
 static PyObject *
 MidiAdsr_setExp(MidiAdsr *self, PyObject *arg)
 {
-	if (PyNumber_Check(arg)) {
+    if (PyNumber_Check(arg)) {
         MYFLT tmp = PyFloat_AsDouble(arg);
         if (tmp > 0.0)
             self->exp = tmp;
@@ -3186,10 +3245,10 @@ PyTypeObject MidiAdsrType = {
     "MidiAdsr objects. Generates MidiAdsr envelope signal.",           /* tp_doc */
     (traverseproc)MidiAdsr_traverse,   /* tp_traverse */
     (inquiry)MidiAdsr_clear,           /* tp_clear */
-    0,		               /* tp_richcompare */
-    0,		               /* tp_weaklistoffset */
-    0,		               /* tp_iter */
-    0,		               /* tp_iternext */
+    0,                       /* tp_richcompare */
+    0,                       /* tp_weaklistoffset */
+    0,                       /* tp_iter */
+    0,                       /* tp_iternext */
     MidiAdsr_methods,             /* tp_methods */
     MidiAdsr_members,             /* tp_members */
     0,                      /* tp_getset */
@@ -3311,7 +3370,7 @@ MidiDelAdsr_setProcMode(MidiDelAdsr *self)
 
     self->proc_func_ptr = MidiDelAdsr_generates;
 
-	switch (muladdmode) {
+    switch (muladdmode) {
         case 0:
             self->muladd_func_ptr = MidiDelAdsr_postprocessing_ii;
             break;
@@ -3384,8 +3443,8 @@ MidiDelAdsr_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     MidiDelAdsr *self;
     self = (MidiDelAdsr *)type->tp_alloc(type, 0);
 
-	self->modebuffer[0] = 0;
-	self->modebuffer[1] = 0;
+    self->modebuffer[0] = 0;
+    self->modebuffer[1] = 0;
     self->topValue = 0.0;
     self->fademode = 0;
     self->changed = 0;
@@ -3463,7 +3522,7 @@ static PyObject * MidiDelAdsr_inplace_div(MidiDelAdsr *self, PyObject *arg) { IN
 static PyObject *
 MidiDelAdsr_setDelay(MidiDelAdsr *self, PyObject *arg)
 {
-	if (PyNumber_Check(arg)) {
+    if (PyNumber_Check(arg)) {
         self->delay = PyFloat_AsDouble(arg);
         self->delayPlusAttack = self->delay + self->attack;
         self->delayPlusAttackPlusDecay = self->delay + self->attack + self->decay;
@@ -3475,7 +3534,7 @@ MidiDelAdsr_setDelay(MidiDelAdsr *self, PyObject *arg)
 static PyObject *
 MidiDelAdsr_setAttack(MidiDelAdsr *self, PyObject *arg)
 {
-	if (PyNumber_Check(arg)) {
+    if (PyNumber_Check(arg)) {
         self->attack = PyFloat_AsDouble(arg);
         if (self->attack < 0.000001)
             self->attack = 0.000001;
@@ -3490,7 +3549,7 @@ MidiDelAdsr_setAttack(MidiDelAdsr *self, PyObject *arg)
 static PyObject *
 MidiDelAdsr_setDecay(MidiDelAdsr *self, PyObject *arg)
 {
-	if (PyNumber_Check(arg)) {
+    if (PyNumber_Check(arg)) {
         self->decay = PyFloat_AsDouble(arg);
         if (self->decay < 0.000001)
             self->decay = 0.000001;
@@ -3504,7 +3563,7 @@ MidiDelAdsr_setDecay(MidiDelAdsr *self, PyObject *arg)
 static PyObject *
 MidiDelAdsr_setSustain(MidiDelAdsr *self, PyObject *arg)
 {
-	if (PyNumber_Check(arg)) {
+    if (PyNumber_Check(arg)) {
         self->sustain = PyFloat_AsDouble(arg);
         if (self->sustain < 0.0)
             self->sustain = 0.0;
@@ -3518,7 +3577,7 @@ MidiDelAdsr_setSustain(MidiDelAdsr *self, PyObject *arg)
 static PyObject *
 MidiDelAdsr_setRelease(MidiDelAdsr *self, PyObject *arg)
 {
-	if (PyNumber_Check(arg)) {
+    if (PyNumber_Check(arg)) {
         self->release = PyFloat_AsDouble(arg);
         if (self->release < 0.000001)
             self->release = 0.000001;
@@ -3531,7 +3590,7 @@ MidiDelAdsr_setRelease(MidiDelAdsr *self, PyObject *arg)
 static PyObject *
 MidiDelAdsr_setExp(MidiDelAdsr *self, PyObject *arg)
 {
-	if (PyNumber_Check(arg)) {
+    if (PyNumber_Check(arg)) {
         MYFLT tmp = PyFloat_AsDouble(arg);
         if (tmp > 0.0)
             self->exp = tmp;
@@ -3633,10 +3692,10 @@ PyTypeObject MidiDelAdsrType = {
     "MidiDelAdsr objects. Generates MidiDelAdsr envelope signal.",           /* tp_doc */
     (traverseproc)MidiDelAdsr_traverse,   /* tp_traverse */
     (inquiry)MidiDelAdsr_clear,           /* tp_clear */
-    0,		               /* tp_richcompare */
-    0,		               /* tp_weaklistoffset */
-    0,		               /* tp_iter */
-    0,		               /* tp_iternext */
+    0,                       /* tp_richcompare */
+    0,                       /* tp_weaklistoffset */
+    0,                       /* tp_iter */
+    0,                       /* tp_iternext */
     MidiDelAdsr_methods,             /* tp_methods */
     MidiDelAdsr_members,             /* tp_members */
     0,                      /* tp_getset */
@@ -3669,8 +3728,8 @@ RawMidi_compute_next_data_frame(RawMidi *self)
 
     if (count > 0) {
         PyObject *tup;
-        for (i=count-1; i>=0; i--) {
-            status = PyoMidi_MessageStatus(buffer[i].message);	// Temp note event holders
+        for (i=0; i<count; i++) {
+            status = PyoMidi_MessageStatus(buffer[i].message);    // Temp note event holders
             data1 = PyoMidi_MessageData1(buffer[i].message);
             data2 = PyoMidi_MessageData2(buffer[i].message);
             tup = PyTuple_New(3);
@@ -3741,21 +3800,21 @@ static PyObject * RawMidi_stop(RawMidi *self) { STOP };
 static PyObject *
 RawMidi_setFunction(RawMidi *self, PyObject *arg)
 {
-	PyObject *tmp;
+    PyObject *tmp;
 
-	if (! PyCallable_Check(arg)) {
+    if (! PyCallable_Check(arg)) {
         PyErr_SetString(PyExc_TypeError, "The callable attribute must be a valid Python function.");
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
+        Py_INCREF(Py_None);
+        return Py_None;
+    }
 
     tmp = arg;
     Py_XDECREF(self->callable);
     Py_INCREF(tmp);
     self->callable = tmp;
 
-	Py_INCREF(Py_None);
-	return Py_None;
+    Py_INCREF(Py_None);
+    return Py_None;
 }
 
 static PyMemberDef RawMidi_members[] = {
@@ -3797,10 +3856,10 @@ PyTypeObject RawMidiType = {
     "RawMidi objects. Calls a function with midi data as arguments.",           /* tp_doc */
     (traverseproc)RawMidi_traverse,   /* tp_traverse */
     (inquiry)RawMidi_clear,           /* tp_clear */
-    0,		               /* tp_richcompare */
-    0,		               /* tp_weaklistoffset */
-    0,		               /* tp_iter */
-    0,		               /* tp_iternext */
+    0,                       /* tp_richcompare */
+    0,                       /* tp_weaklistoffset */
+    0,                       /* tp_iter */
+    0,                       /* tp_iternext */
     RawMidi_methods,             /* tp_methods */
     RawMidi_members,             /* tp_members */
     0,                      /* tp_getset */
diff --git a/src/objects/oscilmodule.c b/src/objects/oscilmodule.c
index 4380f24..3041548 100644
--- a/src/objects/oscilmodule.c
+++ b/src/objects/oscilmodule.c
@@ -12674,4 +12674,494 @@ TableScale_members,             /* tp_members */
 0,      /* tp_init */
 0,                         /* tp_alloc */
 TableScale_new,                 /* tp_new */
-};
\ No newline at end of file
+};
+
+/******************************/
+/* TableFill object definition */
+/******************************/
+typedef struct {
+    pyo_audio_HEAD
+    PyObject *input;
+    Stream *input_stream;
+    PyObject *table;
+    int pointer;
+} TableFill;
+
+static void
+TableFill_compute_next_data_frame(TableFill *self)
+{
+    int i;
+    int size = TableStream_getSize(self->table);
+    MYFLT *tablelist = TableStream_getData(self->table);
+    MYFLT *in = Stream_getData((Stream *)self->input_stream);
+
+    for (i=0; i<self->bufsize; i++) {
+        tablelist[self->pointer++] = in[i];
+        if (self->pointer >= size)
+            self->pointer = 0;
+    }
+}
+
+static int
+TableFill_traverse(TableFill *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->input);
+    Py_VISIT(self->input_stream);
+    Py_VISIT(self->table);
+    return 0;
+}
+
+static int
+TableFill_clear(TableFill *self)
+{
+    pyo_CLEAR
+    Py_CLEAR(self->input);
+    Py_CLEAR(self->input_stream);
+    Py_CLEAR(self->table);
+    return 0;
+}
+
+static void
+TableFill_dealloc(TableFill* self)
+{
+    pyo_DEALLOC
+    TableFill_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+TableFill_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i;
+    PyObject *inputtmp, *input_streamtmp, *tabletmp;
+    TableFill *self;
+    self = (TableFill *)type->tp_alloc(type, 0);
+
+    self->pointer = 0;
+
+    INIT_OBJECT_COMMON
+
+    Stream_setFunctionPtr(self->stream, TableFill_compute_next_data_frame);
+
+    static char *kwlist[] = {"input", "table", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, &inputtmp, &tabletmp))
+        Py_RETURN_NONE;
+
+    INIT_INPUT_STREAM
+
+    if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) {
+        PyErr_SetString(PyExc_TypeError, "\"table\" argument of TableFill must be a PyoTableObject.\n");
+        Py_RETURN_NONE;
+    }
+    Py_XDECREF(self->table);
+    self->table = PyObject_CallMethod((PyObject *)tabletmp, "getTableStream", "");
+
+    PyObject_CallMethod(self->server, "addStream", "O", self->stream);
+
+    return (PyObject *)self;
+}
+
+static PyObject * TableFill_getServer(TableFill* self) { GET_SERVER };
+static PyObject * TableFill_getStream(TableFill* self) { GET_STREAM };
+
+static PyObject * TableFill_play(TableFill *self, PyObject *args, PyObject *kwds)
+{
+    self->pointer = 0;
+    PLAY
+};
+
+static PyObject * TableFill_stop(TableFill *self) { STOP };
+
+static PyObject *
+TableFill_setTable(TableFill *self, PyObject *arg)
+{
+	PyObject *tmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	tmp = arg;
+    Py_INCREF(tmp);
+	Py_DECREF(self->table);
+    self->table = PyObject_CallMethod((PyObject *)tmp, "getTableStream", "");
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject * TableFill_getCurrentPos(TableFill *self) { 
+    return PyLong_FromLong(self->pointer);
+};
+
+static PyMemberDef TableFill_members[] = {
+{"server", T_OBJECT_EX, offsetof(TableFill, server), 0, "Pyo server."},
+{"stream", T_OBJECT_EX, offsetof(TableFill, stream), 0, "Stream object."},
+{"input", T_OBJECT_EX, offsetof(TableFill, input), 0, "Input sound object."},
+{"table", T_OBJECT_EX, offsetof(TableFill, table), 0, "Table to record in."},
+{NULL}  /* Sentinel */
+};
+
+static PyMethodDef TableFill_methods[] = {
+{"getServer", (PyCFunction)TableFill_getServer, METH_NOARGS, "Returns server object."},
+{"_getStream", (PyCFunction)TableFill_getStream, METH_NOARGS, "Returns stream object."},
+{"setTable", (PyCFunction)TableFill_setTable, METH_O, "Sets a new table to fill."},
+{"play", (PyCFunction)TableFill_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+{"stop", (PyCFunction)TableFill_stop, METH_NOARGS, "Stops computing."},
+{"getCurrentPos", (PyCFunction)TableFill_getCurrentPos, METH_NOARGS, "Returns the current position."},
+{NULL}  /* Sentinel */
+};
+
+PyTypeObject TableFillType = {
+PyVarObject_HEAD_INIT(NULL, 0)
+"_pyo.TableFill_base",         /*tp_name*/
+sizeof(TableFill),         /*tp_basicsize*/
+0,                         /*tp_itemsize*/
+(destructor)TableFill_dealloc, /*tp_dealloc*/
+0,                         /*tp_print*/
+0,                         /*tp_getattr*/
+0,                         /*tp_setattr*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
+0,                         /*tp_repr*/
+0,             /*tp_as_number*/
+0,                         /*tp_as_sequence*/
+0,                         /*tp_as_mapping*/
+0,                         /*tp_hash */
+0,                         /*tp_call*/
+0,                         /*tp_str*/
+0,                         /*tp_getattro*/
+0,                         /*tp_setattro*/
+0,                         /*tp_as_buffer*/
+Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
+"TableFill objects. Fill a table object with values in input.",           /* tp_doc */
+(traverseproc)TableFill_traverse,   /* tp_traverse */
+(inquiry)TableFill_clear,           /* tp_clear */
+0,		               /* tp_richcompare */
+0,		               /* tp_weaklistoffset */
+0,		               /* tp_iter */
+0,		               /* tp_iternext */
+TableFill_methods,             /* tp_methods */
+TableFill_members,             /* tp_members */
+0,                      /* tp_getset */
+0,                         /* tp_base */
+0,                         /* tp_dict */
+0,                         /* tp_descr_get */
+0,                         /* tp_descr_set */
+0,                         /* tp_dictoffset */
+0,      /* tp_init */
+0,                         /* tp_alloc */
+TableFill_new,                 /* tp_new */
+};
+
+/**************/
+/* TableScan object */
+/**************/
+typedef struct {
+    pyo_audio_HEAD
+    PyObject *table;
+    int modebuffer[2];
+    int pointerPos;
+} TableScan;
+
+static void
+TableScan_readframes(TableScan *self) {
+    int i;
+    MYFLT *tablelist = TableStream_getData(self->table);
+    int size = TableStream_getSize(self->table);
+
+    for (i=0; i<self->bufsize; i++) {
+        self->data[i] = tablelist[self->pointerPos++];
+        if (self->pointerPos >= size)
+            self->pointerPos = 0;
+    }
+}
+
+static void TableScan_postprocessing_ii(TableScan *self) { POST_PROCESSING_II };
+static void TableScan_postprocessing_ai(TableScan *self) { POST_PROCESSING_AI };
+static void TableScan_postprocessing_ia(TableScan *self) { POST_PROCESSING_IA };
+static void TableScan_postprocessing_aa(TableScan *self) { POST_PROCESSING_AA };
+static void TableScan_postprocessing_ireva(TableScan *self) { POST_PROCESSING_IREVA };
+static void TableScan_postprocessing_areva(TableScan *self) { POST_PROCESSING_AREVA };
+static void TableScan_postprocessing_revai(TableScan *self) { POST_PROCESSING_REVAI };
+static void TableScan_postprocessing_revaa(TableScan *self) { POST_PROCESSING_REVAA };
+static void TableScan_postprocessing_revareva(TableScan *self) { POST_PROCESSING_REVAREVA };
+
+static void
+TableScan_setProcMode(TableScan *self)
+{
+    int muladdmode;
+    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
+
+    self->proc_func_ptr = TableScan_readframes;
+
+	switch (muladdmode) {
+        case 0:
+            self->muladd_func_ptr = TableScan_postprocessing_ii;
+            break;
+        case 1:
+            self->muladd_func_ptr = TableScan_postprocessing_ai;
+            break;
+        case 2:
+            self->muladd_func_ptr = TableScan_postprocessing_revai;
+            break;
+        case 10:
+            self->muladd_func_ptr = TableScan_postprocessing_ia;
+            break;
+        case 11:
+            self->muladd_func_ptr = TableScan_postprocessing_aa;
+            break;
+        case 12:
+            self->muladd_func_ptr = TableScan_postprocessing_revaa;
+            break;
+        case 20:
+            self->muladd_func_ptr = TableScan_postprocessing_ireva;
+            break;
+        case 21:
+            self->muladd_func_ptr = TableScan_postprocessing_areva;
+            break;
+        case 22:
+            self->muladd_func_ptr = TableScan_postprocessing_revareva;
+            break;
+    }
+}
+
+static void
+TableScan_compute_next_data_frame(TableScan *self)
+{
+    (*self->proc_func_ptr)(self);
+    (*self->muladd_func_ptr)(self);
+}
+
+static int
+TableScan_traverse(TableScan *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->table);
+    return 0;
+}
+
+static int
+TableScan_clear(TableScan *self)
+{
+    pyo_CLEAR
+    Py_CLEAR(self->table);
+    return 0;
+}
+
+static void
+TableScan_dealloc(TableScan* self)
+{
+    pyo_DEALLOC
+    TableScan_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+TableScan_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i;
+    PyObject *tabletmp, *multmp=NULL, *addtmp=NULL;
+    TableScan *self;
+    self = (TableScan *)type->tp_alloc(type, 0);
+
+	self->modebuffer[0] = 0;
+	self->modebuffer[1] = 0;
+    self->pointerPos = 0;
+
+    INIT_OBJECT_COMMON
+    Stream_setFunctionPtr(self->stream, TableScan_compute_next_data_frame);
+    self->mode_func_ptr = TableScan_setProcMode;
+
+    static char *kwlist[] = {"table", "mul", "add", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &tabletmp, &multmp, &addtmp))
+        Py_RETURN_NONE;
+
+    if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) {
+        PyErr_SetString(PyExc_TypeError, "\"table\" argument of TableScan must be a PyoTableObject.\n");
+        Py_RETURN_NONE;
+    }
+    Py_XDECREF(self->table);
+    self->table = PyObject_CallMethod((PyObject *)tabletmp, "getTableStream", "");
+
+    if (multmp) {
+        PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp);
+    }
+
+    if (addtmp) {
+        PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp);
+    }
+
+    PyObject_CallMethod(self->server, "addStream", "O", self->stream);
+
+    (*self->mode_func_ptr)(self);
+
+    return (PyObject *)self;
+}
+
+static PyObject * TableScan_getServer(TableScan* self) { GET_SERVER };
+static PyObject * TableScan_getStream(TableScan* self) { GET_STREAM };
+static PyObject * TableScan_setMul(TableScan *self, PyObject *arg) { SET_MUL };
+static PyObject * TableScan_setAdd(TableScan *self, PyObject *arg) { SET_ADD };
+static PyObject * TableScan_setSub(TableScan *self, PyObject *arg) { SET_SUB };
+static PyObject * TableScan_setDiv(TableScan *self, PyObject *arg) { SET_DIV };
+
+static PyObject * TableScan_play(TableScan *self, PyObject *args, PyObject *kwds)
+{
+    self->pointerPos = 0;
+    PLAY
+};
+
+static PyObject * TableScan_out(TableScan *self, PyObject *args, PyObject *kwds)
+{
+    self->pointerPos = 0;
+    OUT
+};
+static PyObject * TableScan_stop(TableScan *self) { STOP };
+
+static PyObject * TableScan_multiply(TableScan *self, PyObject *arg) { MULTIPLY };
+static PyObject * TableScan_inplace_multiply(TableScan *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * TableScan_add(TableScan *self, PyObject *arg) { ADD };
+static PyObject * TableScan_inplace_add(TableScan *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * TableScan_sub(TableScan *self, PyObject *arg) { SUB };
+static PyObject * TableScan_inplace_sub(TableScan *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * TableScan_div(TableScan *self, PyObject *arg) { DIV };
+static PyObject * TableScan_inplace_div(TableScan *self, PyObject *arg) { INPLACE_DIV };
+
+static PyObject *
+TableScan_getTable(TableScan* self)
+{
+    Py_INCREF(self->table);
+    return self->table;
+};
+
+static PyObject *
+TableScan_setTable(TableScan *self, PyObject *arg)
+{
+	PyObject *tmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	tmp = arg;
+	Py_DECREF(self->table);
+    self->table = PyObject_CallMethod((PyObject *)tmp, "getTableStream", "");
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+TableScan_reset(TableScan *self)
+{
+    self->pointerPos = 0;
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyMemberDef TableScan_members[] = {
+{"server", T_OBJECT_EX, offsetof(TableScan, server), 0, "Pyo server."},
+{"stream", T_OBJECT_EX, offsetof(TableScan, stream), 0, "Stream object."},
+{"table", T_OBJECT_EX, offsetof(TableScan, table), 0, "Waveform table."},
+{"mul", T_OBJECT_EX, offsetof(TableScan, mul), 0, "Mul factor."},
+{"add", T_OBJECT_EX, offsetof(TableScan, add), 0, "Add factor."},
+{NULL}  /* Sentinel */
+};
+
+static PyMethodDef TableScan_methods[] = {
+{"getTable", (PyCFunction)TableScan_getTable, METH_NOARGS, "Returns waveform table object."},
+{"getServer", (PyCFunction)TableScan_getServer, METH_NOARGS, "Returns server object."},
+{"_getStream", (PyCFunction)TableScan_getStream, METH_NOARGS, "Returns stream object."},
+{"play", (PyCFunction)TableScan_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+{"out", (PyCFunction)TableScan_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+{"stop", (PyCFunction)TableScan_stop, METH_NOARGS, "Stops computing."},
+{"setTable", (PyCFunction)TableScan_setTable, METH_O, "Sets oscillator table."},
+{"reset", (PyCFunction)TableScan_reset, METH_NOARGS, "Resets pointer position to 0."},
+{"setMul", (PyCFunction)TableScan_setMul, METH_O, "Sets oscillator mul factor."},
+{"setAdd", (PyCFunction)TableScan_setAdd, METH_O, "Sets oscillator add factor."},
+{"setSub", (PyCFunction)TableScan_setSub, METH_O, "Sets oscillator inverse add factor."},
+{"setDiv", (PyCFunction)TableScan_setDiv, METH_O, "Sets inverse mul factor."},
+{NULL}  /* Sentinel */
+};
+
+static PyNumberMethods TableScan_as_number = {
+(binaryfunc)TableScan_add,                      /*nb_add*/
+(binaryfunc)TableScan_sub,                 /*nb_subtract*/
+(binaryfunc)TableScan_multiply,                 /*nb_multiply*/
+INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
+0,                /*nb_remainder*/
+0,                   /*nb_divmod*/
+0,                   /*nb_power*/
+0,                  /*nb_neg*/
+0,                /*nb_pos*/
+0,                  /*(unaryfunc)array_abs,*/
+0,                    /*nb_nonzero*/
+0,                    /*nb_invert*/
+0,               /*nb_lshift*/
+0,              /*nb_rshift*/
+0,              /*nb_and*/
+0,              /*nb_xor*/
+0,               /*nb_or*/
+INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
+0,                       /*nb_int*/
+0,                      /*nb_long*/
+0,                     /*nb_float*/
+INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
+(binaryfunc)TableScan_inplace_add,              /*inplace_add*/
+(binaryfunc)TableScan_inplace_sub,         /*inplace_subtract*/
+(binaryfunc)TableScan_inplace_multiply,         /*inplace_multiply*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
+0,        /*inplace_remainder*/
+0,           /*inplace_power*/
+0,       /*inplace_lshift*/
+0,      /*inplace_rshift*/
+0,      /*inplace_and*/
+0,      /*inplace_xor*/
+0,       /*inplace_or*/
+0,             /*nb_floor_divide*/
+(binaryfunc)TableScan_div,                       /*nb_true_divide*/
+0,     /*nb_inplace_floor_divide*/
+(binaryfunc)TableScan_inplace_div,                       /*nb_inplace_true_divide*/
+0,                     /* nb_index */
+};
+
+PyTypeObject TableScanType = {
+PyVarObject_HEAD_INIT(NULL, 0)
+"_pyo.TableScan_base",         /*tp_name*/
+sizeof(TableScan),         /*tp_basicsize*/
+0,                         /*tp_itemsize*/
+(destructor)TableScan_dealloc, /*tp_dealloc*/
+0,                         /*tp_print*/
+0,                         /*tp_getattr*/
+0,                         /*tp_setattr*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
+0,                         /*tp_repr*/
+&TableScan_as_number,             /*tp_as_number*/
+0,                         /*tp_as_sequence*/
+0,                         /*tp_as_mapping*/
+0,                         /*tp_hash */
+0,                         /*tp_call*/
+0,                         /*tp_str*/
+0,                         /*tp_getattro*/
+0,                         /*tp_setattro*/
+0,                         /*tp_as_buffer*/
+Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
+"TableScan objects. Scan the content of a table in loop.",           /* tp_doc */
+(traverseproc)TableScan_traverse,   /* tp_traverse */
+(inquiry)TableScan_clear,           /* tp_clear */
+0,		               /* tp_richcompare */
+0,		               /* tp_weaklistoffset */
+0,		               /* tp_iter */
+0,		               /* tp_iternext */
+TableScan_methods,             /* tp_methods */
+TableScan_members,             /* tp_members */
+0,                      /* tp_getset */
+0,                         /* tp_base */
+0,                         /* tp_dict */
+0,                         /* tp_descr_get */
+0,                         /* tp_descr_set */
+0,                         /* tp_dictoffset */
+0,      /* tp_init */
+0,                         /* tp_alloc */
+TableScan_new,                 /* tp_new */
+};
diff --git a/src/objects/patternmodule.c b/src/objects/patternmodule.c
index a54553f..db95d6e 100644
--- a/src/objects/patternmodule.c
+++ b/src/objects/patternmodule.c
@@ -176,8 +176,6 @@ Pattern_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     Stream_setFunctionPtr(self->stream, Pattern_compute_next_data_frame);
     self->mode_func_ptr = Pattern_setProcMode;
 
-    Stream_setStreamActive(self->stream, 0);
-
     self->sampleToSec = 1. / self->sr;
     self->currentTime = 0.;
 
@@ -195,7 +193,14 @@ Pattern_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     }
 
     if (argtmp) {
-        PyObject_CallMethod((PyObject *)self, "setArg", "O", argtmp);
+        if (PyTuple_Check(argtmp)) {
+            PyObject *argument = PyTuple_New(1);
+            PyTuple_SetItem(argument, 0, argtmp);
+            PyObject_CallMethod((PyObject *)self, "setArg", "O", argument);
+        }
+        else {
+            PyObject_CallMethod((PyObject *)self, "setArg", "O", argtmp);
+        }
     }
 
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
diff --git a/src/objects/phasevocmodule.c b/src/objects/phasevocmodule.c
index f2b9666..73b9d58 100644
--- a/src/objects/phasevocmodule.c
+++ b/src/objects/phasevocmodule.c
@@ -5623,6 +5623,71 @@ PVShift_new,                                     /* tp_new */
 /*****************/
 /** PVAmpMod **/
 /*****************/
+static void
+PVMod_setTable(MYFLT *table, int shape) {
+    int i;
+
+    if (shape < 0 || shape > 7)
+        shape = 0;
+
+    if (shape == 0) {
+        for (i=0; i<8192; i++)
+            table[i] = (MYFLT)(MYSIN(TWOPI * i / 8192.0) * 0.5 + 0.5);
+    }
+    else if (shape == 1) {
+        for (i=0; i<8192; i++)
+            table[i] = (MYFLT)(1.0 - (i / 8191.0));
+    }
+    else if (shape == 2) {
+        for (i=0; i<8192; i++)
+            table[i] = (MYFLT)(i / 8191.0);
+    }
+    else if (shape == 3) {
+        for (i=0; i<4096; i++)
+            table[i] = 1.0;
+        for (i=4096; i<8192; i++)
+            table[i] = 0.0;
+    }
+    else if (shape == 4) {
+        for (i=0; i<2048; i++)
+            table[i] = (MYFLT)(i / 4095.0) + 0.5;
+        for (i=2048; i<6144; i++)
+            table[i] = (MYFLT)(1.0 - ((i - 2048) / 4095.0));
+        for (i=6144; i<8192; i++)
+            table[i] = (MYFLT)((i - 6144) / 4095.0);
+    }
+    else if (shape == 5) {
+        MYFLT val = RANDOM_UNIFORM;
+        table[0] = val;
+        for (i=1; i<8192; i++) {
+            val += RANDOM_UNIFORM * 0.04 - 0.02;
+            if (val < 0)
+                val = -val;
+            else if (val >= 1.0)
+                val = 1.0 - (val - 1.0);
+            table[i] = val;
+        }
+    }
+    else if (shape == 6) {
+        MYFLT val = RANDOM_UNIFORM;
+        table[0] = val;
+        for (i=1; i<8192; i++) {
+            val += RANDOM_UNIFORM * 0.14 - 0.07;
+            if (val < 0)
+                val = -val;
+            else if (val >= 1.0)
+                val = 1.0 - (val - 1.0);
+            table[i] = val;
+        }
+    }
+    else if (shape == 7) {
+        for (i=0; i<8192; i++) {
+            table[i] = RANDOM_UNIFORM;
+        }
+    }
+    table[8192] = table[0];
+}
+
 typedef struct {
     pyo_audio_HEAD
     PyObject *input;
@@ -5919,7 +5984,7 @@ PVAmpMod_dealloc(PVAmpMod* self)
 static PyObject *
 PVAmpMod_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
-    int i;
+    int i, shape = 0;
     PyObject *inputtmp, *input_streamtmp, *basefreqtmp=NULL, *spreadtmp=NULL;
     PVAmpMod *self;
     self = (PVAmpMod *)type->tp_alloc(type, 0);
@@ -5932,9 +5997,9 @@ PVAmpMod_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     Stream_setFunctionPtr(self->stream, PVAmpMod_compute_next_data_frame);
     self->mode_func_ptr = PVAmpMod_setProcMode;
 
-    static char *kwlist[] = {"input", "basefreq", "spread", NULL};
+    static char *kwlist[] = {"input", "basefreq", "spread", "shape", NULL};
 
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &basefreqtmp, &spreadtmp))
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOi", kwlist, &inputtmp, &basefreqtmp, &spreadtmp, &shape))
         Py_RETURN_NONE;
 
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) {
@@ -5967,9 +6032,7 @@ PVAmpMod_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->count = (int *)realloc(self->count, self->bufsize * sizeof(int));
 
     self->table = (MYFLT *)realloc(self->table, 8193 * sizeof(MYFLT));
-    for (i=0; i<8192; i++)
-        self->table[i] = (MYFLT)(MYSIN(TWOPI * i / 8192.0) * 0.5 + 0.5);
-    self->table[8192] = 0.5;
+    PVMod_setTable(self->table, shape);
 
     PVAmpMod_realloc_memories(self);
 
@@ -6071,6 +6134,19 @@ PVAmpMod_setSpread(PVAmpMod *self, PyObject *arg)
 }
 
 static PyObject *
+PVAmpMod_setShape(PVAmpMod *self, PyObject *arg)
+{
+    ASSERT_ARG_NOT_NULL
+
+	if (PyNumber_Check(arg)) {
+        PVMod_setTable(self->table, PyInt_AsLong(arg));
+    }
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
 PVAmpMod_reset(PVAmpMod *self) {
     int i;
     for (i=0; i<self->hsize; i++)
@@ -6096,6 +6172,7 @@ static PyMethodDef PVAmpMod_methods[] = {
 {"setInput", (PyCFunction)PVAmpMod_setInput, METH_O, "Sets a new input object."},
 {"setBasefreq", (PyCFunction)PVAmpMod_setBasefreq, METH_O, "Sets the modulator's base frequency."},
 {"setSpread", (PyCFunction)PVAmpMod_setSpread, METH_O, "Sets the high frequency spreading factor."},
+{"setShape", (PyCFunction)PVAmpMod_setShape, METH_O, "Sets the modulation oscillator waveform."},
 {"reset", (PyCFunction)PVAmpMod_reset, METH_NOARGS, "Resets pointer positions."},
 {"play", (PyCFunction)PVAmpMod_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
 {"stop", (PyCFunction)PVAmpMod_stop, METH_NOARGS, "Stops computing."},
@@ -6516,7 +6593,7 @@ PVFreqMod_dealloc(PVFreqMod* self)
 static PyObject *
 PVFreqMod_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
-    int i;
+    int i, shape = 0;
     PyObject *inputtmp, *input_streamtmp, *basefreqtmp=NULL, *spreadtmp=NULL, *depthtmp=NULL;
     PVFreqMod *self;
     self = (PVFreqMod *)type->tp_alloc(type, 0);
@@ -6530,9 +6607,9 @@ PVFreqMod_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     Stream_setFunctionPtr(self->stream, PVFreqMod_compute_next_data_frame);
     self->mode_func_ptr = PVFreqMod_setProcMode;
 
-    static char *kwlist[] = {"input", "basefreq", "spread", "depth", NULL};
+    static char *kwlist[] = {"input", "basefreq", "spread", "depth", "shape", NULL};
 
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist, &inputtmp, &basefreqtmp, &spreadtmp, &depthtmp))
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOi", kwlist, &inputtmp, &basefreqtmp, &spreadtmp, &depthtmp, &shape))
         Py_RETURN_NONE;
 
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) {
@@ -6569,9 +6646,7 @@ PVFreqMod_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->count = (int *)realloc(self->count, self->bufsize * sizeof(int));
 
     self->table = (MYFLT *)realloc(self->table, 8193 * sizeof(MYFLT));
-    for (i=0; i<8192; i++)
-        self->table[i] = (MYFLT)(MYSIN(TWOPI * i / 8192.0) * 0.5 + 0.5);
-    self->table[8192] = 0.5;
+    PVMod_setTable(self->table, shape);
 
     PVFreqMod_realloc_memories(self);
 
@@ -6704,6 +6779,19 @@ PVFreqMod_setDepth(PVFreqMod *self, PyObject *arg)
 }
 
 static PyObject *
+PVFreqMod_setShape(PVFreqMod *self, PyObject *arg)
+{
+    ASSERT_ARG_NOT_NULL
+
+	if (PyNumber_Check(arg)) {
+        PVMod_setTable(self->table, PyInt_AsLong(arg));
+    }
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
 PVFreqMod_reset(PVFreqMod *self) {
     int i;
     for (i=0; i<self->hsize; i++)
@@ -6731,6 +6819,7 @@ static PyMethodDef PVFreqMod_methods[] = {
 {"setBasefreq", (PyCFunction)PVFreqMod_setBasefreq, METH_O, "Sets the modulator's base frequency."},
 {"setSpread", (PyCFunction)PVFreqMod_setSpread, METH_O, "Sets the high frequency spreading factor."},
 {"setDepth", (PyCFunction)PVFreqMod_setDepth, METH_O, "Sets the modulator's depth."},
+{"setShape", (PyCFunction)PVFreqMod_setShape, METH_O, "Sets the modulation oscillator waveform."},
 {"reset", (PyCFunction)PVFreqMod_reset, METH_NOARGS, "Resets pointer positions."},
 {"play", (PyCFunction)PVFreqMod_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
 {"stop", (PyCFunction)PVFreqMod_stop, METH_NOARGS, "Stops computing."},
diff --git a/src/objects/tablemodule.c b/src/objects/tablemodule.c
index c8514df..880a464 100644
--- a/src/objects/tablemodule.c
+++ b/src/objects/tablemodule.c
@@ -31,6 +31,11 @@
 #include "wind.h"
 #include "fft.h"
 
+#if !defined(_WIN32) && !defined(_WIN64)
+#include <fcntl.h>
+#include <sys/mman.h>
+#endif
+
 #define __TABLE_MODULE
 #include "tablemodule.h"
 #undef __TABLE_MODULE
@@ -4866,7 +4871,6 @@ NewTable_new,                 /* tp_new */
 /***********************/
 typedef struct {
     pyo_table_HEAD
-    int pointer;
 } DataTable;
 
 static void
@@ -4907,8 +4911,6 @@ DataTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
     self->server = PyServer_get_server();
 
-    self->pointer = 0;
-
     MAKE_NEW_TABLESTREAM(self->tablestream, &TableStreamType, NULL);
 
     static char *kwlist[] = {"size", "init", NULL};
@@ -5827,7 +5829,6 @@ TableRec_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     INIT_OBJECT_COMMON
 
     Stream_setFunctionPtr(self->stream, TableRec_compute_next_data_frame);
-    Stream_setStreamActive(self->stream, 0);
 
     static char *kwlist[] = {"input", "table", "fadetime", NULL};
 
@@ -7087,7 +7088,6 @@ TablePut_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     INIT_OBJECT_COMMON
 
     Stream_setFunctionPtr(self->stream, TablePut_compute_next_data_frame);
-    Stream_setStreamActive(self->stream, 0);
 
     static char *kwlist[] = {"input", "table", NULL};
 
@@ -7218,6 +7218,7 @@ typedef struct {
     Stream *pos_stream;
     NewTable *table;
     int mode;
+    int maxwindow;
     int lastPos;
     MYFLT lastValue;
     int count;
@@ -7260,10 +7261,14 @@ TableWrite_compute_next_data_frame(TableWrite *self)
                 int steps, dir;
                 if (ipos > self->lastPos) { /* Move forward. */
                     steps = ipos - self->lastPos;
+                    if (steps > self->maxwindow)
+                        steps = 1;
                     dir = 1;
                 }
                 else { /* Move backward. */
                     steps = self->lastPos - ipos;
+                    if (steps > self->maxwindow)
+                        steps = 1;
                     dir = -1;
                 }
                 self->valInTable = tablelist[ipos];
@@ -7327,6 +7332,7 @@ TableWrite_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self = (TableWrite *)type->tp_alloc(type, 0);
 
     self->mode = 0;
+    self->maxwindow = 1024;
     self->lastPos = -1;
     self->lastValue = 0.0;
     self->count = 0;
@@ -7336,11 +7342,10 @@ TableWrite_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     INIT_OBJECT_COMMON
 
     Stream_setFunctionPtr(self->stream, TableWrite_compute_next_data_frame);
-    Stream_setStreamActive(self->stream, 1);
 
-    static char *kwlist[] = {"input", "pos", "table", "mode", NULL};
+    static char *kwlist[] = {"input", "pos", "table", "mode", "maxwindow", NULL};
 
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "OOOi", kwlist, &inputtmp, &postmp, &tabletmp, &self->mode))
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "OOOii", kwlist, &inputtmp, &postmp, &tabletmp, &self->mode, &self->maxwindow))
         Py_RETURN_NONE;
 
     INIT_INPUT_STREAM
@@ -7469,3 +7474,224 @@ TableWrite_members,             /* tp_members */
 0,                         /* tp_alloc */
 TableWrite_new,                 /* tp_new */
 };
+
+/*************************/
+/* SharedTable structure */
+/*************************/
+typedef struct {
+    pyo_table_HEAD
+    char *name;
+    int create;
+    int fd;
+} SharedTable;
+
+static int
+SharedTable_traverse(SharedTable *self, visitproc visit, void *arg)
+{
+    pyo_table_VISIT
+    return 0;
+}
+
+static int
+SharedTable_clear(SharedTable *self)
+{
+    pyo_table_CLEAR
+    return 0;
+}
+
+static void
+SharedTable_dealloc(SharedTable* self)
+{
+#if !defined(_WIN32) && !defined(_WIN64)
+    close(self->fd);
+    if (self->create)
+        shm_unlink(self->name);
+#endif
+    SharedTable_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+SharedTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i;
+    SharedTable *self;
+    self = (SharedTable *)type->tp_alloc(type, 0);
+
+    self->server = PyServer_get_server();
+
+    MAKE_NEW_TABLESTREAM(self->tablestream, &TableStreamType, NULL);
+
+    static char *kwlist[] = {"name", "create", "size", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "sii", kwlist, &self->name, &self->create, &self->size))
+        Py_RETURN_NONE;
+
+#if !defined(_WIN32) && !defined(_WIN64)
+    /* Open shared memory object. */
+    if (self->create) {
+        self->fd = shm_open(self->name, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
+        if (self->fd == -1) {
+            PySys_WriteStdout("SharedTable: failed to create shared memory.\n");
+            Py_RETURN_NONE;
+        }
+
+        if (ftruncate(self->fd, sizeof(MYFLT) * (self->size + 1)) == -1) {
+            PySys_WriteStdout("SharedTable: failed to truncate shared memory.\n");
+            close(self->fd);
+            shm_unlink(self->name);
+            Py_RETURN_NONE;
+        }
+    }
+    else {
+        self->fd = shm_open(self->name, O_RDWR, 0);
+        if (self->fd == -1) {
+            PySys_WriteStdout("SharedTable: failed to create shared memory.\n");
+            Py_RETURN_NONE;
+        }
+    }
+
+    /* Map shared memory object. */
+    self->data = mmap(NULL, sizeof(MYFLT) * (self->size + 1),
+                      PROT_READ | PROT_WRITE, MAP_SHARED, self->fd, 0);
+    if (self->data == MAP_FAILED) {
+        PySys_WriteStdout("SharedTable: failed to mmap shared memory.\n");
+        close(self->fd);
+        if (self->create)
+            shm_unlink(self->name);
+        Py_RETURN_NONE;
+    }
+
+    /* Initialize the memory. */
+    if (self->create) {
+        for (i=0; i<=self->size; i++) {
+            self->data[i] = 0.0;
+        }
+    }
+#endif
+
+    TableStream_setSize(self->tablestream, self->size);
+    TableStream_setData(self->tablestream, self->data);
+
+    double sr = PyFloat_AsDouble(PyObject_CallMethod(self->server, "getSamplingRate", NULL));
+    TableStream_setSamplingRate(self->tablestream, sr);
+
+    return (PyObject *)self;
+}
+
+static PyObject * SharedTable_getServer(SharedTable* self) { GET_SERVER };
+static PyObject * SharedTable_getTableStream(SharedTable* self) { GET_TABLE_STREAM };
+static PyObject * SharedTable_setData(SharedTable *self, PyObject *arg) { SET_TABLE_DATA };
+static PyObject * SharedTable_normalize(SharedTable *self) { NORMALIZE };
+static PyObject * SharedTable_reset(SharedTable *self) { TABLE_RESET };
+static PyObject * SharedTable_removeDC(SharedTable *self) { REMOVE_DC };
+static PyObject * SharedTable_reverse(SharedTable *self) { REVERSE };
+static PyObject * SharedTable_invert(SharedTable *self) { INVERT };
+static PyObject * SharedTable_rectify(SharedTable *self) { RECTIFY };
+static PyObject * SharedTable_bipolarGain(SharedTable *self, PyObject *args, PyObject *kwds) { TABLE_BIPOLAR_GAIN };
+static PyObject * SharedTable_lowpass(SharedTable *self, PyObject *args, PyObject *kwds) { TABLE_LOWPASS };
+static PyObject * SharedTable_fadein(SharedTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEIN };
+static PyObject * SharedTable_fadeout(SharedTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEOUT };
+static PyObject * SharedTable_pow(SharedTable *self, PyObject *args, PyObject *kwds) { TABLE_POWER };
+static PyObject * SharedTable_copy(SharedTable *self, PyObject *arg) { COPY };
+static PyObject * SharedTable_copyData(SharedTable *self, PyObject *args, PyObject *kwds) { TABLE_COPYDATA };
+static PyObject * SharedTable_rotate(SharedTable *self, PyObject *args, PyObject *kwds) { TABLE_ROTATE };
+static PyObject * SharedTable_setTable(SharedTable *self, PyObject *arg) { SET_TABLE };
+static PyObject * SharedTable_getTable(SharedTable *self) { GET_TABLE };
+static PyObject * SharedTable_getViewTable(SharedTable *self, PyObject *args, PyObject *kwds) { GET_VIEW_TABLE };
+static PyObject * SharedTable_put(SharedTable *self, PyObject *args, PyObject *kwds) { TABLE_PUT };
+static PyObject * SharedTable_get(SharedTable *self, PyObject *args, PyObject *kwds) { TABLE_GET };
+static PyObject * SharedTable_add(SharedTable *self, PyObject *arg) { TABLE_ADD };
+static PyObject * SharedTable_sub(SharedTable *self, PyObject *arg) { TABLE_SUB };
+static PyObject * SharedTable_mul(SharedTable *self, PyObject *arg) { TABLE_MUL };
+
+static PyObject *
+SharedTable_getSize(SharedTable *self)
+{
+    return PyInt_FromLong(self->size);
+};
+
+static PyObject *
+SharedTable_getRate(SharedTable *self)
+{
+    MYFLT sr = PyFloat_AsDouble(PyObject_CallMethod(self->server, "getSamplingRate", NULL)); \
+    return PyFloat_FromDouble(sr / self->size);
+};
+
+static PyMemberDef SharedTable_members[] = {
+    {"server", T_OBJECT_EX, offsetof(SharedTable, server), 0, "Pyo server."},
+    {"tablestream", T_OBJECT_EX, offsetof(SharedTable, tablestream), 0, "Table stream object."},
+    {NULL}  /* Sentinel */
+};
+
+static PyMethodDef SharedTable_methods[] = {
+    {"getServer", (PyCFunction)SharedTable_getServer, METH_NOARGS, "Returns server object."},
+    {"copy", (PyCFunction)SharedTable_copy, METH_O, "Copy data from table given in argument."},
+    {"copyData", (PyCFunction)SharedTable_copyData, METH_VARARGS|METH_KEYWORDS, "Copy data from table given in argument."},
+    {"rotate", (PyCFunction)SharedTable_rotate, METH_VARARGS|METH_KEYWORDS, "Rotate table around position as argument."},
+    {"setTable", (PyCFunction)SharedTable_setTable, METH_O, "Sets the table content from a list of floats (must be the same size as the object size)."},
+    {"getTable", (PyCFunction)SharedTable_getTable, METH_NOARGS, "Returns a list of table samples."},
+    {"getViewTable", (PyCFunction)SharedTable_getViewTable, METH_VARARGS|METH_KEYWORDS, "Returns a list of pixel coordinates for drawing the table."},
+    {"getTableStream", (PyCFunction)SharedTable_getTableStream, METH_NOARGS, "Returns table stream object created by this table."},
+    {"setData", (PyCFunction)SharedTable_setData, METH_O, "Sets the table from samples in a text file."},
+    {"normalize", (PyCFunction)SharedTable_normalize, METH_NOARGS, "Normalize table samples between -1 and 1"},
+    {"reset", (PyCFunction)SharedTable_reset, METH_NOARGS, "Resets table samples to 0.0"},
+    {"removeDC", (PyCFunction)SharedTable_removeDC, METH_NOARGS, "Filter out DC offset from the table's data."},
+    {"reverse", (PyCFunction)SharedTable_reverse, METH_NOARGS, "Reverse the table's data."},
+    {"invert", (PyCFunction)SharedTable_invert, METH_NOARGS, "Reverse the table's data in amplitude."},
+    {"rectify", (PyCFunction)SharedTable_rectify, METH_NOARGS, "Positive rectification of the table's data."},
+    {"bipolarGain", (PyCFunction)SharedTable_bipolarGain, METH_VARARGS|METH_KEYWORDS, "Apply different amp values to positive and negative samples."},
+    {"lowpass", (PyCFunction)SharedTable_lowpass, METH_VARARGS|METH_KEYWORDS, "Apply a one-pole lowpass filter on table's samples."},
+    {"fadein", (PyCFunction)SharedTable_fadein, METH_VARARGS|METH_KEYWORDS, "Apply a gradual increase in the level of the table's samples."},
+    {"fadeout", (PyCFunction)SharedTable_fadeout, METH_VARARGS|METH_KEYWORDS, "Apply a gradual decrease in the level of the table's samples."},
+    {"pow", (PyCFunction)SharedTable_pow, METH_VARARGS|METH_KEYWORDS, "Apply a power function on each sample in the table."},
+    {"put", (PyCFunction)SharedTable_put, METH_VARARGS|METH_KEYWORDS, "Puts a value at specified position in the table."},
+    {"get", (PyCFunction)SharedTable_get, METH_VARARGS|METH_KEYWORDS, "Gets the value at specified position in the table."},
+    {"getSize", (PyCFunction)SharedTable_getSize, METH_NOARGS, "Return the size of the table in samples."},
+    {"getRate", (PyCFunction)SharedTable_getRate, METH_NOARGS, "Return the frequency (in cps) that reads the sound without pitch transposition."},
+    {"add", (PyCFunction)SharedTable_add, METH_O, "Performs table addition."},
+    {"sub", (PyCFunction)SharedTable_sub, METH_O, "Performs table substraction."},
+    {"mul", (PyCFunction)SharedTable_mul, METH_O, "Performs table multiplication."},
+    {NULL}  /* Sentinel */
+};
+
+PyTypeObject SharedTableType = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "_pyo.SharedTable_base",         /*tp_name*/
+    sizeof(SharedTable),         /*tp_basicsize*/
+    0,                         /*tp_itemsize*/
+    (destructor)SharedTable_dealloc, /*tp_dealloc*/
+    0,                         /*tp_print*/
+    0,                         /*tp_getattr*/
+    0,                         /*tp_setattr*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
+    0,                         /*tp_repr*/
+    0,                         /*tp_as_number*/
+    0,                         /*tp_as_sequence*/
+    0,                         /*tp_as_mapping*/
+    0,                         /*tp_hash */
+    0,                         /*tp_call*/
+    0,                         /*tp_str*/
+    0,                         /*tp_getattro*/
+    0,                         /*tp_setattro*/
+    0,                         /*tp_as_buffer*/
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
+    "SharedTable objects. Generates an empty table.",  /* tp_doc */
+    (traverseproc)SharedTable_traverse,   /* tp_traverse */
+    (inquiry)SharedTable_clear,           /* tp_clear */
+    0,		               /* tp_richcompare */
+    0,		               /* tp_weaklistoffset */
+    0,		               /* tp_iter */
+    0,		               /* tp_iternext */
+    SharedTable_methods,             /* tp_methods */
+    SharedTable_members,             /* tp_members */
+    0,                      /* tp_getset */
+    0,                         /* tp_base */
+    0,                         /* tp_dict */
+    0,                         /* tp_descr_get */
+    0,                         /* tp_descr_set */
+    0,                         /* tp_dictoffset */
+    0,      /* tp_init */
+    0,                         /* tp_alloc */
+    SharedTable_new,                 /* tp_new */
+};
diff --git a/src/objects/trigmodule.c b/src/objects/trigmodule.c
index 201696a..d17d070 100644
--- a/src/objects/trigmodule.c
+++ b/src/objects/trigmodule.c
@@ -1337,7 +1337,14 @@ TrigFunc_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     }
 
     if (argtmp) {
-        PyObject_CallMethod((PyObject *)self, "setArg", "O", argtmp);
+        if (PyTuple_Check(argtmp)) {
+            PyObject *argument = PyTuple_New(1);
+            PyTuple_SetItem(argument, 0, argtmp);
+            PyObject_CallMethod((PyObject *)self, "setArg", "O", argument);
+        }
+        else {
+            PyObject_CallMethod((PyObject *)self, "setArg", "O", argtmp);
+        }
     }
 
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
diff --git a/utils/E-Pyo.py b/utils/E-Pyo.py
index b7c05b9..eca8bd4 100755
--- a/utils/E-Pyo.py
+++ b/utils/E-Pyo.py
@@ -3784,7 +3784,7 @@ class Editor(stc.StyledTextCtrl):
         if ext in ["py", "pyw", "c5"]:
             self.SetLexer(stc.STC_LEX_PYTHON)
             self.SetStyleBits(self.GetStyleBitsNeeded())
-            self.SetKeyWords(0, " ".join(keyword.kwlist) + " None True False ")
+            self.SetKeyWords(0, " ".join(keyword.kwlist) + " None True False print ")
             self.SetKeyWords(1, " ".join(PYO_WORDLIST))
             self.StyleSetSpec(stc.STC_P_DEFAULT, buildStyle('default'))
             self.StyleSetSpec(stc.STC_P_COMMENTLINE, buildStyle('comment'))
diff --git a/utils/PyoDoc.py b/utils/PyoDoc.py
old mode 100644
new mode 100755
index b88322b..6de22e7
--- a/utils/PyoDoc.py
+++ b/utils/PyoDoc.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 # encoding: utf-8
 from __future__ import print_function
-import subprocess, threading, os, sys, unicodedata
+import subprocess, threading, os, sys, unicodedata, inspect
 import wx
 import wx.stc as stc
 from wx.lib.embeddedimage import PyEmbeddedImage
@@ -225,7 +225,7 @@ under the current Python distribution to access these classes.
 _DOC_KEYWORDS = ['Attributes', 'Examples', 'Methods', 'Notes', 'Methods details',
                  'Parentclass', 'Overview', 'Initline', 'Description', 'Parameters']
 _HEADERS = ["Server", "PyoObjectBase", "Map", "Stream", "TableStream", "functions",
-            "MidiListener", "OscListener", "PyoGui"]
+            "MidiListener", "MidiDispatcher", "OscListener", "PyoGui"]
 _KEYWORDS_LIST = ['SLMap']
 _KEYWORDS_LIST.extend(_HEADERS)
 _NUM_PAGES = 1
@@ -247,14 +247,21 @@ for k1 in _HEADERS:
         _KEYWORDS_LIST.extend(OBJECTS_TREE[k1])
         _NUM_PAGES += len(OBJECTS_TREE[k1])
 
-PYOOBJECTBASE_METHODS_FILTER = [x[0] for x in inspect.getmembers(PyoObjectBase, inspect.ismethod)]
-PYOOBJECT_METHODS_FILTER = [x[0] for x in inspect.getmembers(PyoObject, inspect.ismethod)]
-PYOMATRIXOBJECT_METHODS_FILTER = [x[0] for x in inspect.getmembers(PyoMatrixObject, inspect.ismethod)]
-PYOTABLEOBJECT_METHODS_FILTER = [x[0] for x in inspect.getmembers(PyoTableObject, inspect.ismethod)]
-PYOPVOBJECT_METHODS_FILTER = [x[0] for x in inspect.getmembers(PyoPVObject, inspect.ismethod)]
-MAP_METHODS_FILTER = [x[0] for x in inspect.getmembers(Map, inspect.ismethod)]
-SLMAP_METHODS_FILTER = [x[0] for x in inspect.getmembers(SLMap, inspect.ismethod)]
-WXPANEL_METHODS_FILTER = [x[0] for x in inspect.getmembers(wx.Panel, inspect.ismethod)]
+def get_object_methods(obj, filter=[]):
+    o = eval(obj)
+    meths = [f for f in dir(o) if callable(getattr(o, f))]
+    meths = [f for f in meths if not f.startswith("__") and not f.startswith("_")]
+    meths = [f for f in meths if f not in filter]
+    return meths
+
+PYOOBJECTBASE_METHODS_FILTER = get_object_methods("PyoObjectBase")
+PYOOBJECT_METHODS_FILTER = get_object_methods("PyoObject")
+PYOMATRIXOBJECT_METHODS_FILTER = get_object_methods("PyoMatrixObject")
+PYOTABLEOBJECT_METHODS_FILTER = get_object_methods("PyoTableObject")
+PYOPVOBJECT_METHODS_FILTER = get_object_methods("PyoPVObject")
+MAP_METHODS_FILTER = get_object_methods("Map")
+SLMAP_METHODS_FILTER = get_object_methods("SLMap")
+WXPANEL_METHODS_FILTER = get_object_methods("wx.Panel")
 
 def _ed_set_style(editor, searchKey=None):
     editor.SetLexer(stc.STC_LEX_PYTHON)
@@ -747,7 +754,7 @@ class ManualPanel(wx.Treebook):
             filter = WXPANEL_METHODS_FILTER
         else:
             filter = []
-        obj_meths = [x[0] for x in inspect.getmembers(eval(obj), inspect.ismethod) if x[0] not in filter]
+        obj_meths = get_object_methods(obj, filter)
         methods = ''
         for meth in obj_meths:
             docstr = getattr(eval(obj), meth).__doc__
@@ -1065,7 +1072,15 @@ class RunningThread(threading.Thread):
 
     def kill(self):
         self.terminated = True
-        self.proc.terminate()
+        if PLATFORM == "win32":
+            try:
+                os.system("Taskkill /PID %d /F" % self.proc.pid)
+            except:
+                print('"Taskkill" does not succeed to kill the process %d.' % self.proc.pid)
+        else:
+            self.proc.terminate()
+        if self.proc.poll() == None:
+            self.proc.kill()
 
     def run(self):
         if self.osx_app_bundled:
@@ -1073,23 +1088,23 @@ class RunningThread(threading.Thread):
             prelude = "export -n %s;export PATH=/usr/local/bin:/usr/local/lib:$PATH;env;" % vars_to_remove
             if self.caller_need_to_invoke_32_bit:
                 self.proc = subprocess.Popen(["%s%s%s %s" % (prelude, self.set_32_bit_arch, self.which_python, self.path)],
-                                shell=True, cwd=self.cwd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+                                universal_newlines=True, shell=True, cwd=self.cwd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
             else:
                 self.proc = subprocess.Popen(["%s%s %s" % (prelude, self.which_python, self.path)], cwd=self.cwd,
-                                    shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+                                    universal_newlines=True, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
         elif wx.Platform == '__WXMAC__':
             if self.caller_need_to_invoke_32_bit:
                 self.proc = subprocess.Popen(["%s%s %s" % (self.set_32_bit_arch, self.which_python, self.path)],
-                                shell=True, cwd=self.cwd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+                                universal_newlines=True, shell=True, cwd=self.cwd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
             else:
                 self.proc = subprocess.Popen(["%s %s" % (self.which_python, self.path)], cwd=self.cwd,
-                                shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+                                universal_newlines=True, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
         elif wx.Platform == "__WXMSW__":
-                self.proc = subprocess.Popen([self.which_python, self.path], cwd=self.cwd,
-                                shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+                self.proc = subprocess.Popen([self.which_python, "-u", self.path], cwd=ensureNFD(self.cwd),
+                                universal_newlines=True,  shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
         else:
                 self.proc = subprocess.Popen([self.which_python, self.path], cwd=self.cwd,
-                                stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+                                universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
 
 
         while self.proc.poll() == None and not self.terminated:
diff --git a/utils/epyo_builder_win32.py b/utils/epyo_builder_win32.py
index 70fd483..b9856ad 100644
--- a/utils/epyo_builder_win32.py
+++ b/utils/epyo_builder_win32.py
@@ -14,8 +14,7 @@ shutil.copytree("snippets", "Resources/snippets")
 shutil.copytree("styles", "Resources/styles")
 
 if version[0] < 3:
-    os.system('C:\Python%d%d\Scripts\pyi-makespec -F -c --icon=Resources\E-PyoIcon.ico "E-Pyo.py"' % version)
-    os.system('C:\Python%d%d\Scripts\pyi-build "E-Pyo.spec"' % version)
+    os.system('C:\Python%d%d\Scripts\pyinstaller --clean -F -c --icon=Resources\E-PyoIcon.ico "E-Pyo.py"' % version)
 else:
     os.system('pyinstaller --clean -F -c --icon=Resources\E-PyoIcon.ico "E-Pyo.py"')
 
diff --git a/utils/setup.py b/utils/setup.py
index 165595d..e9e05e9 100644
--- a/utils/setup.py
+++ b/utils/setup.py
@@ -16,11 +16,11 @@ OPTIONS = {'argv_emulation': False,
                'CFBundleExecutable': 'E-Pyo',
                'CFBundleIconFile': 'E-PyoIcon.icns',
                'CFBundleIdentifier': 'com.ajaxsoundstudio.E-Pyo',
-               'CFBundleInfoDictionaryVersion': '0.8.1',
+               'CFBundleInfoDictionaryVersion': '0.8.3',
                'CFBundleName': 'E-Pyo',
                'CFBundlePackageType': 'APPL',
-               'CFBundleShortVersionString': '0.8.1',
-               'CFBundleVersion': '0.8.1',
+               'CFBundleShortVersionString': '0.8.3',
+               'CFBundleVersion': '0.8.3',
                'CFBundleDocumentTypes': [{'CFBundleTypeOSTypes': ['TEXT'],
                                           'CFBundleTypeExtensions': ['py'],
                                           'CFBundleTypeRole': 'Editor',

-- 
python-pyo packaging



More information about the pkg-multimedia-commits mailing list